diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..af4450fc07 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +target/ export-ignore +*.log export-ignore +.idea/ export-ignore +._* export-ignore +._*/ export-ignore +.repository/ export-ignore +.classpath export-ignore +.project export-ignore +.settings/ export-ignore +bower_compoments/ export-ignore +node_modules/ export-ignore +dist/ export-ignore +dist_cov/ export-ignore +portal/index.html export-ignore +portal/index-debug.html export-ignore +*.nupkg export-ignore +*.dll export-ignore diff --git a/.gitignore b/.gitignore index b516ec8fea..dcf923b745 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ target # Icon must ends with two \r. Icon +/website/tmp # Thumbnails ._* @@ -32,7 +33,9 @@ Icon .settings/ .metadata/ #Webstorm artifacts +#Webstorm/IntelliJ artifacts .idea/ +*.iml stack/corepersistence/collection/nbactions.xml stack/corepersistence/graph/nbactions.xml stack/corepersistence/model/nbactions.xml @@ -56,6 +59,7 @@ usergrid-UNIT.properties /portal/js/templates.js /portal/index.html /portal/index-debug.html +/portal/dist/* /portal/dist/usergrid-portal/ /portal/dist/appsvc-ui/ /portal/nbproject/project.properties @@ -82,3 +86,8 @@ portal/js/templates.js !/stack/corepersistence/common/src/test/resources/usergrid-UNIT.properties *.iml sdks/dotnet/samples/notifications/packages/* +/sdks/html5-javascript/node_modules/ + + +/stack/rest_integration_tests/node_modules +/stack/rest_integration_tests/config/override.js diff --git a/.usergridversion b/.usergridversion new file mode 100644 index 0000000000..6753471d56 --- /dev/null +++ b/.usergridversion @@ -0,0 +1 @@ +2.0.0-SNAPSHOT diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000000..3e5c736b69 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,65 @@ + +Usergrid 2.1.0 +-------------------------------------------------------------------------------- + +Usergrid 2.1.0 is a major release of Usergrid with a completely rewritten +persistence, index and query engine based on Cassandra and ElasticSearch. +The REST API remains the same as in Usergrid 1.x but with the addition of some +new system APIs for managing the query index and data migrations. + +Usergrid 2.1.0 will not work with a Usergrid 1.x database and currently +there is no migration tool for upgrading a 1.x system to 2.1. + + +Usergrid 1.0.2 +-------------------------------------------------------------------------------- + +Usergrid 1.0.2 is a minor release with bug fixes and small improvements. +Here are the highlights: + +Bugs fixed + +* S3 upload fails on OpenJDK and Java 8 (fixed by JClouds upgrade) +* Asset data deleted when connection to Asset deleted +* Portal stores app password as clear-text + +Improvements + +* Cassandra key-space names are now configurable + +New features + +* ExportAdmins: a new tool to export Admin Users, credentials and organizations +* ImportAdmins: a new tool to import Admin Users, credentials and organizations +* Central SSO: Usergrid-Usergrid SSO via new /management/externaltoken end-point + +Here's the full list of JIRA issues resolved: +https://issues.apache.org/jira/issues/?jql=project%3Dusergrid%20and%20fixVersion%3D1.0.2 + + +Usergrid 1.0.1 +-------------------------------------------------------------------------------- + +Except for our shiny new PHP5 SDK, Usergrid 1.0.1 is mostly a bug fix release. +Here are the highlights: + +* New PHP5 SDK - new SDK is a Guzzle Web service descriptor so any Usergrid API + calls can be added with ease. + +* Original PHP SDK - added URL endpoint update functionality. + +* Node.js SDK - Bug fix: calcTimeDiff changed to return seconds correctly +* Node.js SDK - Bug fix: getOnExist was sending wrong data value to server. + +* Android SDK Updated from Apigee source. Numerous bug fixes and enhancements. + +* Docs moved to readthedocs.org: http://usergrid.readthedocs.org/en/latest/. + +* Admin portal - Changed default config to point to localhost. +* Admin portal - Build now created as zip file during build process. + +* Stack - Bug fix: Launcher now works, uses Admin portal hosted on ASF Infra. +* Stack - Bug fix: reset password will now work with or without reCaptcha keys. +* Stack - Build now works with latest versions of Maven. +* Stack - Build now supports property for configurable argline parameters. +* Stack - Build now sets java.awt.headless to prevent forkedbooter popups. diff --git a/DISCLAIMER b/DISCLAIMER deleted file mode 100644 index ffd2c60a50..0000000000 --- a/DISCLAIMER +++ /dev/null @@ -1,9 +0,0 @@ -DISCLAIMER - -Apache Usergrid is an effort undergoing incubation at The Apache Software -Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of -all newly accepted projects until a further review indicates that the -infrastructure, communications, and decision making process have stabilized -in a manner consistent with other successful ASF projects. While incubation -status is not necessarily a reflection of the completeness or stability of the -code, it does indicate that the project has yet to be fully endorsed by the ASF. diff --git a/LICENSE b/LICENSE index 64c7ebcea9..a4b9abe87b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,6 @@ +Apache Usergrid itself is licensed under the terms of the Apache License: + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -201,6 +203,7 @@ See the License for the specific language governing permissions and limitations under the License. +------------------------------------------------------------------------------ USERGRID SUBCOMPONENTS @@ -213,7 +216,7 @@ IOS SDK ------- For the SBJson component: - Copyright (C) 2009-2011 Stig Brautaset. All rights reserved. + Copyright (c) Stig Brautaset. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -240,10 +243,10 @@ For the SBJson component: OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - For the SSKeychain component: +----------------------------- - Copyright (c) 2010-2014 Sam Soffes, http://soff.es + Copyright (c) Sam Soffes, http://soff.es Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -264,28 +267,61 @@ For the SSKeychain component: OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). +Other components: +----------------- + +This product bundles angular.js +Copyright(c) Google, Inc. Released under the MIT license. + +This product bundles angular-scenario.js, part of jQuery JavaScript Library +which Includes Sizzle.js Copyright (c) jQuery Foundation, Inc. and others. +Released under the MIT license. + +This product bundles Bootstrap Copyright (c) Twitter, Inc +Licensed under the MIT license. + +The product bundles Intro.js (MIT licensed) +Copyright (c) usabli.ca - A weekend project by Afshin Mehrabani (@afshinmeh) + +This product bundles jQuery +Licensed under MIT license. + +This product bundles jQuery-UI +Licensed under MIT license. + +This product bundles jQuery Sparklines (New BSD License) +Copyright (c) Splunk Inc. + +This product bundles Mocha. +All rights reserved. Licensed under MIT. +Copyright (c) TJ Holowaychuk + +This product bundles NewtonSoft.Json under MIT license + +This product bundles NPM MD5 (BSD-3 licensed) +Copyright (c) Paul Vorbach and Copyright (C), Jeff Mott. + +This product bundles NSubsttute under BSD license This product bundles SBJson, which is available under a "3-clause BSD" license. For details, see sdks/ios/UGAPI/SBJson/ . +This product bundles Sphinx under BSD license + This product bundles SSKeychain, which is available under a "MIT/X11" license. For details, see sdks/ios/UGAPI/SSKeychain/. -This product bundles angular-senario.js, part of jQuery JavaScript Library v1.10.2 -which Includes Sizzle.js Copyright 2005, 2013 jQuery Foundation, Inc. and -other contributors. Released under the MIT license. +This product bundles SSToolkit. +Copyright (c) Sam Soffes. All rights reserved. +These files can be located within the /sdks/ios package. + +This product bundles Entypo, CC by SA license -This product bundles angular.js, specifically AngularJS v1.2.5 (c) 2010-2014 -Google, Inc. Released under the MIT license. +This product bundles date.min.js, MIT license -This product bundles Bootstrap v2.3.2 Copyright 2012 Twitter, Inc -Licensed under the Apache License v2.0 +This product bundles jquery.ui.timepicker.min.js, MIT license -This product bundles jquery-ui-1.8.9. Licensed under MIT license. +This product bundles blanket_mocha.min.js, MIT license -This product bundles jquery-1.9.1 Licensed under MIT license. +This product bundles FontAwesome, SIL Open Font License -This product bundles mocha. All rights reserved. Licensed under MIT. -Copyright (c) 2011-2014 TJ Holowaychuk diff --git a/NOTICE b/NOTICE index 1fc37a405e..765a303013 100644 --- a/NOTICE +++ b/NOTICE @@ -1,6 +1,5 @@ -Apache Usergrid_ -Copyright 2014 The Apache Software Foundation. +Apache Usergrid +Copyright 2015 The Apache Software Foundation. -This product bundles SSToolkit Copyright (c) 2009-2011 Sam Soffes. All rights reserved. -These files can be located within the /sdks/ios package. - \ No newline at end of file +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/README-Docs.md b/README-Docs.md new file mode 100644 index 0000000000..9d74c887cf --- /dev/null +++ b/README-Docs.md @@ -0,0 +1,13 @@ +Apache Usergrid Website and Docs +================================ + +Usergrid docs and website can be found in these directories: + +* __website__: This is the source for the website, it is written in Markdown and uses Pandoc to generate HTML. +* __docs__: This is the source for the documentation, it is written in Markdown and uses Sphinx to generate HTML. +* __contents__: This is the target directory for our website and docs generation tools. + +Refer to the README files in the __website__ and __docs__ directories for instructions on how to add and modify +the website and docs, how to run the generators and how to ensure that the __contents__ directory gets published +to __usergrid.apache.org__. + diff --git a/README.md b/README.md index 4c735105e9..ca63047523 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,20 @@ Apache Usergrid =============== - -__WARNING__: This is the __two-dot-o__ branch and work is underway here on a new persistence system for Usergrid. Not everything is working in this branch. If you want stability, you should be working against the master branch or a tag. We refer to the new persistence system as Core Persistence and you can find its modules in the stack/corepersistence directory. - - Overview -------- -**Apache Usergrid is a multi-tenant Backend-as-a-Service stack for web & mobile applications, based on RESTful APIs. It is [currently incubating at the Apache Software Foundation](http://usergrid.incubator.apache.org/).** +**Usergrid is a multi-tenant Backend-as-a-Service stack for web & mobile apps, based on RESTful APIs.** -##Contributing -We accept all contributions via our GitHub, so you can fork our repo (apache/incubator-usergrid) and then submit a PR back to us for approval. For larger PRs you'll need to have an ICLA form on file with Apache. For more information see our [Contribution Workflow Policy](https://cwiki.apache.org/confluence/display/usergrid/Usergrid+Contribution+Workflow), and specifically our [External Contributors Guide](https://cwiki.apache.org/confluence/display/usergrid/Usergrid+External+Contributors+Guide). +## Contributing -##Build awesome apps with Usergrid! +We accept all contributions via our GitHub, so you can fork our repo (apache/usergrid) and then submit a PR back to us for approval. For larger PRs you'll need to have an ICLA form on file with Apache. For more information see [How to Contribute Code & Docs](http://usergrid.apache.org/docs/reference/contribute-code.html). -Apache Usergrid provides all code necessary to build and power modern mobile applications. This includes the the server stack, administrative portal website, SDKs in most popular languages, as well as command line tools. +## Build awesome apps with Usergrid! -Look for much more detailed README files in their corresponding subdirectories, or check out [our website](http://usergrid.incubator.apache.org/) for more info. +Apache Usergrid provides all code necessary to build and power modern mobile applications. This includes the server stack, administrative portal website, SDKs in most popular languages, as well as command line tools. -* The server-side stack, a Java 7 + Cassandra codebase that powers all of the features, is located under [`/stack`](stack). You can install dependencies and compile it with maven. See [stack/README.md](stack#requirements) for instructions. +* The server-side stack, a Java 8 + Cassandra + ElasticSearch codebase that powers all of the features, is located under [`/stack`](stack). You can install dependencies and compile it with maven. See [stack/README.md](stack#requirements) for instructions. * The admin portal is a pure HTML5+JavaScript app allowing you to register developers and let them manage their apps in a multi-tenant cluster. Located under [`/portal`](portal) @@ -27,6 +22,7 @@ Look for much more detailed README files in their corresponding subdirectories, * a command-line client “ugc” allowing you to complete most maintenance tasks, as well as queries in a manner similar to the mysql or the mongo shell, located under [`/ugc`](ugc). You can install it on your machine with a simple `sudo gem install ugc` -##For more information -See the [Apache Usergrid web site](http://usergrid.incubator.apache.org/). +## For more information + +See the Apache Usergrid [web site](http://usergrid.apache.org) and [documentation](http://usergrid.apache.org). diff --git a/content/README.md b/content/README.md new file mode 100644 index 0000000000..0bbec7ee8c --- /dev/null +++ b/content/README.md @@ -0,0 +1,7 @@ +# Generated Website and Docs Content + +__DO NOT EDIT FILES IN THIS DIRECTORY__ + +The files here were generated by tools in the ``/docs`` and ``/website`` directories. + +See the README files there for information about updating the docs and website. \ No newline at end of file diff --git a/content/bootstrap/bootstrap.min.css b/content/bootstrap/bootstrap.min.css new file mode 100644 index 0000000000..93c646fe1e --- /dev/null +++ b/content/bootstrap/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v3.0.0 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world by @mdo and @fat. + *//*! normalize.css v2.1.0 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:100%}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{padding:0;box-sizing:border-box}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:2cm .5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}button,input,select[multiple],textarea{background-image:none}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;height:auto;max-width:100%}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16.099999999999998px;font-weight:200;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-warning{color:#c09853}.text-danger{color:#b94a48}.text-success{color:#468847}.text-info{color:#3a87ad}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h1 small,h2 small,h3 small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 small,h5 small,h6 small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:bold}dd{margin-left:0}@media(min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.428571429;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:1.428571429}code,pre{font-family:Monaco,Menlo,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.row{margin-right:-15px;margin-left:-15px}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11{float:left}.col-xs-1{width:8.333333333333332%}.col-xs-2{width:16.666666666666664%}.col-xs-3{width:25%}.col-xs-4{width:33.33333333333333%}.col-xs-5{width:41.66666666666667%}.col-xs-6{width:50%}.col-xs-7{width:58.333333333333336%}.col-xs-8{width:66.66666666666666%}.col-xs-9{width:75%}.col-xs-10{width:83.33333333333334%}.col-xs-11{width:91.66666666666666%}.col-xs-12{width:100%}@media(min-width:768px){.container{max-width:750px}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11{float:left}.col-sm-1{width:8.333333333333332%}.col-sm-2{width:16.666666666666664%}.col-sm-3{width:25%}.col-sm-4{width:33.33333333333333%}.col-sm-5{width:41.66666666666667%}.col-sm-6{width:50%}.col-sm-7{width:58.333333333333336%}.col-sm-8{width:66.66666666666666%}.col-sm-9{width:75%}.col-sm-10{width:83.33333333333334%}.col-sm-11{width:91.66666666666666%}.col-sm-12{width:100%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-3{left:25%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-6{left:50%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-9{left:75%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-11{left:91.66666666666666%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-3{right:25%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-6{right:50%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-9{right:75%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-11{margin-left:91.66666666666666%}}@media(min-width:992px){.container{max-width:970px}.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11{float:left}.col-md-1{width:8.333333333333332%}.col-md-2{width:16.666666666666664%}.col-md-3{width:25%}.col-md-4{width:33.33333333333333%}.col-md-5{width:41.66666666666667%}.col-md-6{width:50%}.col-md-7{width:58.333333333333336%}.col-md-8{width:66.66666666666666%}.col-md-9{width:75%}.col-md-10{width:83.33333333333334%}.col-md-11{width:91.66666666666666%}.col-md-12{width:100%}.col-md-push-0{left:auto}.col-md-push-1{left:8.333333333333332%}.col-md-push-2{left:16.666666666666664%}.col-md-push-3{left:25%}.col-md-push-4{left:33.33333333333333%}.col-md-push-5{left:41.66666666666667%}.col-md-push-6{left:50%}.col-md-push-7{left:58.333333333333336%}.col-md-push-8{left:66.66666666666666%}.col-md-push-9{left:75%}.col-md-push-10{left:83.33333333333334%}.col-md-push-11{left:91.66666666666666%}.col-md-pull-0{right:auto}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-3{right:25%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-6{right:50%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-9{right:75%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-11{right:91.66666666666666%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-3{margin-left:25%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-6{margin-left:50%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-9{margin-left:75%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-11{margin-left:91.66666666666666%}}@media(min-width:1200px){.container{max-width:1170px}.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11{float:left}.col-lg-1{width:8.333333333333332%}.col-lg-2{width:16.666666666666664%}.col-lg-3{width:25%}.col-lg-4{width:33.33333333333333%}.col-lg-5{width:41.66666666666667%}.col-lg-6{width:50%}.col-lg-7{width:58.333333333333336%}.col-lg-8{width:66.66666666666666%}.col-lg-9{width:75%}.col-lg-10{width:83.33333333333334%}.col-lg-11{width:91.66666666666666%}.col-lg-12{width:100%}.col-lg-push-0{left:auto}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-3{left:25%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-6{left:50%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-9{left:75%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-11{left:91.66666666666666%}.col-lg-pull-0{right:auto}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-3{right:25%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-6{right:50%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-9{right:75%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-11{margin-left:91.66666666666666%}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table thead>tr>th,.table tbody>tr>th,.table tfoot>tr>th,.table thead>tr>td,.table tbody>tr>td,.table tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table caption+thead tr:first-child th,.table colgroup+thead tr:first-child th,.table thead:first-child tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed thead>tr>th,.table-condensed tbody>tr>th,.table-condensed tfoot>tr>th,.table-condensed thead>tr>td,.table-condensed tbody>tr>td,.table-condensed tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{display:table-column;float:none}table td[class*="col-"],table th[class*="col-"]{display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8;border-color:#d6e9c6}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6;border-color:#c9e2b3}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede;border-color:#eed3d7}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc;border-color:#e6c1c7}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3;border-color:#fbeed5}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc;border-color:#f8e5be}@media(max-width:768px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0;background-color:#fff}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>thead>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>thead>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:normal;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm{height:auto}.input-lg{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:45px;line-height:45px}textarea.input-lg{height:auto}.has-warning .help-block,.has-warning .control-label{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.has-warning .input-group-addon{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.has-error .help-block,.has-error .control-label{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.has-error .input-group-addon{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.has-success .help-block,.has-success .control-label{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.has-success .input-group-addon{color:#468847;background-color:#dff0d8;border-color:#468847}.form-control-static{padding-top:7px;margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media(min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline .radio,.form-inline .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}@media(min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-link{font-weight:normal;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-xs{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;line-height:1}.glyphicon:empty{width:1em}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-print:before{content:"\e045"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-briefcase:before{content:"\1f4bc"}.glyphicon-calendar:before{content:"\1f4c5"}.glyphicon-pushpin:before{content:"\1f4cc"}.glyphicon-paperclip:before{content:"\1f4ce"}.glyphicon-camera:before{content:"\1f4f7"}.glyphicon-lock:before{content:"\1f512"}.glyphicon-bell:before{content:"\1f514"}.glyphicon-bookmark:before{content:"\1f516"}.glyphicon-fire:before{content:"\1f525"}.glyphicon-wrench:before{content:"\1f527"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid #000;border-right:4px solid transparent;border-bottom:0 dotted;border-left:4px solid transparent;content:""}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#fff;text-decoration:none;background-color:#428bca}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0 dotted;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-default .caret{border-top-color:#333}.btn-primary .caret,.btn-success .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret{border-top-color:#fff}.dropup .btn-default .caret{border-bottom-color:#333}.dropup .btn-primary .caret,.dropup .btn-success .caret,.dropup .btn-warning .caret,.dropup .btn-danger .caret,.dropup .btn-info .caret{border-bottom-color:#fff}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:5px 10px;padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.btn-group-justified .btn{display:table-cell;float:none;width:1%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group.col{float:none;padding-right:0;padding-left:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:45px;line-height:45px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}@media(min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:5px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}@media(min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tabbable:before,.tabbable:after{display:table;content:" "}.tabbable:after{clear:both}.tabbable:before,.tabbable:after{display:table;content:" "}.tabbable:after{clear:both}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.nav .caret{border-top-color:#428bca;border-bottom-color:#428bca}.nav a:hover .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;z-index:1000;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}@media(min-width:768px){.navbar{border-radius:4px}}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-collapse .navbar-nav.navbar-left:first-child{margin-left:-15px}.navbar-collapse .navbar-nav.navbar-right:last-child{margin-right:-15px}.navbar-collapse .navbar-text:last-child{margin-right:0}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-header,.container>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{border-width:0 0 1px}@media(min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;border-width:0 0 1px}@media(min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;z-index:1030}.navbar-fixed-bottom{bottom:0;margin-bottom:0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media(min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;border:1px solid transparent;border-radius:4px}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media(min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media(max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media(min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}@media(min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}@media(min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media(min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-text{float:left;margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{margin-right:15px;margin-left:15px}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e6e6e6}.navbar-default .navbar-nav>.dropdown>a:hover .caret,.navbar-default .navbar-nav>.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.open>a .caret,.navbar-default .navbar-nav>.open>a:hover .caret,.navbar-default .navbar-nav>.open>a:focus .caret{border-top-color:#555;border-bottom-color:#555}.navbar-default .navbar-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eee}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.badge:empty{display:none}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.btn .badge{position:relative;top:-1px}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1{font-size:63px}}.thumbnail{display:inline-block;display:block;height:auto;max-width:100%;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img{display:block;height:auto;max-width:100%}a.thumbnail:hover,a.thumbnail:focus{border-color:#428bca}.thumbnail>img{margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{color:#c09853;background-color:#fcf8e3;border-color:#fbeed5}.alert-warning hr{border-top-color:#f8e5be}.alert-warning .alert-link{color:#a47e3c}.alert-danger{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger hr{border-top-color:#e6c1c7}.alert-danger .alert-link{color:#953b39}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table{margin-bottom:0}.panel>.panel-body+.table{border-top:1px solid #ddd}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-title{margin-top:0;margin-bottom:0;font-size:16px}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#fbeed5}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#fbeed5}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#fbeed5}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#fbeed5}.panel-danger{border-color:#eed3d7}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#eed3d7}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#eed3d7}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}body.modal-open,.modal-open .navbar-fixed-top,.modal-open .navbar-fixed-bottom{margin-right:15px}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{z-index:1050;width:auto;padding:10px;margin-right:auto;margin-left:auto}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{right:auto;left:50%;width:600px;padding-top:30px;padding-bottom:30px}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;height:auto;max-width:100%;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);opacity:.5;filter:alpha(opacity=50)}.carousel-control.left{background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.5)),to(rgba(0,0,0,0.0001)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.5) 0),color-stop(rgba(0,0,0,0.0001) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.0001)),to(rgba(0,0,0,0.5)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.0001) 0),color-stop(rgba(0,0,0,0.5) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1)}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;left:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix:after{clear:both}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.affix{position:fixed}@-ms-viewport{width:device-width}@media screen and (max-width:400px){@-ms-viewport{width:320px}}.hidden{display:none!important;visibility:hidden!important}.visible-xs{display:none!important}tr.visible-xs{display:none!important}th.visible-xs,td.visible-xs{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}tr.visible-xs.visible-sm{display:table-row!important}th.visible-xs.visible-sm,td.visible-xs.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}tr.visible-xs.visible-md{display:table-row!important}th.visible-xs.visible-md,td.visible-xs.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-xs.visible-lg{display:block!important}tr.visible-xs.visible-lg{display:table-row!important}th.visible-xs.visible-lg,td.visible-xs.visible-lg{display:table-cell!important}}.visible-sm{display:none!important}tr.visible-sm{display:none!important}th.visible-sm,td.visible-sm{display:none!important}@media(max-width:767px){.visible-sm.visible-xs{display:block!important}tr.visible-sm.visible-xs{display:table-row!important}th.visible-sm.visible-xs,td.visible-sm.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}tr.visible-sm.visible-md{display:table-row!important}th.visible-sm.visible-md,td.visible-sm.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-sm.visible-lg{display:block!important}tr.visible-sm.visible-lg{display:table-row!important}th.visible-sm.visible-lg,td.visible-sm.visible-lg{display:table-cell!important}}.visible-md{display:none!important}tr.visible-md{display:none!important}th.visible-md,td.visible-md{display:none!important}@media(max-width:767px){.visible-md.visible-xs{display:block!important}tr.visible-md.visible-xs{display:table-row!important}th.visible-md.visible-xs,td.visible-md.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}tr.visible-md.visible-sm{display:table-row!important}th.visible-md.visible-sm,td.visible-md.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-md.visible-lg{display:block!important}tr.visible-md.visible-lg{display:table-row!important}th.visible-md.visible-lg,td.visible-md.visible-lg{display:table-cell!important}}.visible-lg{display:none!important}tr.visible-lg{display:none!important}th.visible-lg,td.visible-lg{display:none!important}@media(max-width:767px){.visible-lg.visible-xs{display:block!important}tr.visible-lg.visible-xs{display:table-row!important}th.visible-lg.visible-xs,td.visible-lg.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}tr.visible-lg.visible-sm{display:table-row!important}th.visible-lg.visible-sm,td.visible-lg.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}tr.visible-lg.visible-md{display:table-row!important}th.visible-lg.visible-md,td.visible-lg.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-lg{display:block!important}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}tr.hidden-xs{display:table-row!important}th.hidden-xs,td.hidden-xs{display:table-cell!important}@media(max-width:767px){.hidden-xs{display:none!important}tr.hidden-xs{display:none!important}th.hidden-xs,td.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm{display:none!important}tr.hidden-xs.hidden-sm{display:none!important}th.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md{display:none!important}tr.hidden-xs.hidden-md{display:none!important}th.hidden-xs.hidden-md,td.hidden-xs.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-xs.hidden-lg{display:none!important}tr.hidden-xs.hidden-lg{display:none!important}th.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}tr.hidden-sm{display:table-row!important}th.hidden-sm,td.hidden-sm{display:table-cell!important}@media(max-width:767px){.hidden-sm.hidden-xs{display:none!important}tr.hidden-sm.hidden-xs{display:none!important}th.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}tr.hidden-sm{display:none!important}th.hidden-sm,td.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md{display:none!important}tr.hidden-sm.hidden-md{display:none!important}th.hidden-sm.hidden-md,td.hidden-sm.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-sm.hidden-lg{display:none!important}tr.hidden-sm.hidden-lg{display:none!important}th.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}tr.hidden-md{display:table-row!important}th.hidden-md,td.hidden-md{display:table-cell!important}@media(max-width:767px){.hidden-md.hidden-xs{display:none!important}tr.hidden-md.hidden-xs{display:none!important}th.hidden-md.hidden-xs,td.hidden-md.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-md.hidden-sm{display:none!important}tr.hidden-md.hidden-sm{display:none!important}th.hidden-md.hidden-sm,td.hidden-md.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}tr.hidden-md{display:none!important}th.hidden-md,td.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-md.hidden-lg{display:none!important}tr.hidden-md.hidden-lg{display:none!important}th.hidden-md.hidden-lg,td.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}tr.hidden-lg{display:table-row!important}th.hidden-lg,td.hidden-lg{display:table-cell!important}@media(max-width:767px){.hidden-lg.hidden-xs{display:none!important}tr.hidden-lg.hidden-xs{display:none!important}th.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm{display:none!important}tr.hidden-lg.hidden-sm{display:none!important}th.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md{display:none!important}tr.hidden-lg.hidden-md{display:none!important}th.hidden-lg.hidden-md,td.hidden-lg.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg{display:none!important}tr.hidden-lg{display:none!important}th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print{display:none!important}tr.visible-print{display:none!important}th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.hidden-print{display:none!important}tr.hidden-print{display:none!important}th.hidden-print,td.hidden-print{display:none!important}} \ No newline at end of file diff --git a/content/community/index.html b/content/community/index.html new file mode 100644 index 0000000000..2ff02f8011 --- /dev/null +++ b/content/community/index.html @@ -0,0 +1,595 @@ + + + + + + Apache Usergrid — + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+

The Apache Usergrid community has members in 170+ cities in 30 countries on 6 continents

+
+
+
+
+ + +
+
+
+
+

Events

+
+
+
+
+

ApacheCon DenverApril 7-9

+

Featuring our very own Dave Johnson who will deliver a talk on "How to contribute to Apache Usergrid"

+

+
+

Seoul Hack Day #1 January 24

+

KT is hosting a Usergrid evening in Gangnam, Seoul, South Korea! Register on OnOffMix.com

+

+
+

SF Bay Area Meetup #1 January 23

+

Can’t join us for the afternoon hack day? We’ll host an evening meetup right afterwards! Or join us for both! Register on Meetup.com

+

+
+

 

+

Want to organize a Usergrid event? Contact us!

+

+
+
+
+ +
+
+
+
+

Live Chat

+
+
+
+
+

HipChat

+

Some of the Usergrid team hangs around in this HipChat Room: https://www.hipchat.com/gDDIQrdQa. Come by and chat for a spell!

+

+
+

IRC

+

Another (less used) option is the Usergrid IRC chat channel #usergrid.

+

+
+
+ +
+
+
+
+

Mailing-lists

+
+
+
+
+

Users

+

Perfect if you build apps against Apache Usergrid or deploy Apache Usergrid.

+

To subscribe, send a blank email to
user-subscribe@usergrid.apache.org.

+

You can also read the archives.

+
+
+

Dev

+

If you are building contributions & modifications to Apache Usergrid’s stack, portal, cli and SDKs, this is the list for you.

+

To subscribe, send a blank email to
dev-subscribe@usergrid.apache.org.

+

You can also read the archives.

+
+
+

Commits

+

This list receives an email whenever new code is contributed to Apache Usergrid.

+

To subscribe, send a blank email to
commits-subscribe@usergrid.apache.org.

+

You can also read the archives.

+
+
+
+
+ +
+ + +
+ +
+
+
+
+

Committers

+
+
+
+
+ +

Alberto Leal

+
+
+ +

Alex Karasulu

+
+
+ +

Askhat Asanaliev

+
+
+ +

Dave Johnson

+
+
+ +

Ed Anuff

+
+
+ +

Furkan Bicak

+
+
+
+
+ +

George Reyes

+
+
+ +

Mike Dunker

+
+
+ +

Michael Russo

+
+
+ +

Nate McCall

+
+
+ +

Rod Simpson

+
+
+ +

Scott Ganyo

+
+
+
+
+ +

Shaozhuang Liu

+
+
+ +

Shawn Feldman

+
+
+ +

Sungju Jin

+
+
+ +

Tim Anglade

+
+
+ +

Todd Nine

+
+
+ +

Yigit Sapli

+
+
+
+
+ +

Jeff West

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+

Tools

+
+
+
+
+ +

IntelliJ IDEA

+
+
+ +

YourKit Java Profiler

+
+
+ +

structure101

+
+
+ These great companies have provided free product licenses to the Apache Usergrid team. We use these tools and love them. Thank you! +
+
+ + + + + + + + + + + + + + diff --git a/content/css/bootflat-extensions.css b/content/css/bootflat-extensions.css new file mode 100644 index 0000000000..513ecaa1b5 --- /dev/null +++ b/content/css/bootflat-extensions.css @@ -0,0 +1,356 @@ +/* + Bootflat 1.0.1 + Designed & Built by flathemes, http://www.flathemes.com + Licensed under MIT License, http://opensource.org/licenses/mit-license.html + + Thanks for supporting our website and enjoy! +*/ +/*------------------------------------*\ + $bubble +\*------------------------------------*/ +.bubble-body { + position: relative; + padding: 3px; + background-color: #ecf0f1; + border-radius: 3px; + overflow: visible; +} +.pull-left ~ .bubble-body { + margin-left: 60px; +} +.pull-right ~ .bubble-body { + margin-right: 60px; +} +.bubble-body .bubble-inner { + min-height: 32px; + border: 1px solid #d3d7d7; + background-color: #fbfbfb; +} +.bubble-body .bubble-heading { + padding: 0 10px; + border-bottom: 1px solid #d3d7d7; + background-color: #f4f4f4; + font-size: 12px; + font-weight: bold; + color: #222; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + height: 33px; + line-height: 33px; +} +.bubble-body .bubble-content { + padding: 10px; + font-size: 13px; + overflow: auto; + width: 100%; + line-height: 1.7; +} +.bubble-body .bubble-inner { + margin-bottom: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.bubble-body .bubble-inner .bubble { + margin: 0 10px; + padding-top: 10px; + border-top: 1px solid #ecf0f1; +} +.bubble-body .bubble-inner .bubble .bubble { + margin: 0; +} +.bubble-body .bubble-inner .bubble-body:before, +.bubble-body .bubble-inner .bubble-body:after { + display: none; +} +.bubble-body .bubble-inner .bubble-body, +.bubble-body .bubble-inner .bubble-inner { + padding: 0; + border: none; + background-color: transparent; +} +.bubble-body .bubble-inner .bubble-inner .bubble-heading { + padding: 0; + border-bottom: none; + background-color: transparent; + height: auto; + line-height: normal; +} +.bubble-body .bubble-inner .bubble-inner .bubble-content { + padding: 0; + font-size: 13px; + overflow: auto; + width: 100%; + line-height: 1.5; +} +.bubble-arrow-left:before, +.bubble-arrow-right:after { + position: absolute; + top: 15px; + content: ""; + display: block; + height: 0; + width: 0; + border-width: 10px; + border-style: solid; +} +.bubble-arrow-left:before { + border-color: transparent #ecf0f1 transparent transparent; + left: -20px; +} +.bubble-arrow-right:after { + border-color: transparent transparent transparent #ecf0f1; + right: -20px; +} +/*------------------------------------*\ + $breadcrumb-arrow +\*------------------------------------*/ +.breadcrumb-arrow { + padding: 0; + list-style:none; + background-color: #ecf0f1; + height:36px; + line-height: 36px; +} +.breadcrumb-arrow li:first-child a { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.breadcrumb-arrow li, +.breadcrumb-arrow li a, +.breadcrumb-arrow li span{ + display:-moz-inline-box; + display:inline-table; + display:inline-block; + zoom:1; + *display:inline; + vertical-align:top; +} +.breadcrumb-arrow li:not(:first-child) { + margin-left: -5px; +} +.breadcrumb-arrow li + li:before { + padding: 0; + content: ""; +} +.breadcrumb-arrow li span { + padding: 0 10px; +} +.breadcrumb-arrow li a, +.breadcrumb-arrow li:not(:first-child) span { + padding:0 10px 0 25px; + height:35px; + line-height:35px; +} +.breadcrumb-arrow li:first-child a { + padding: 0 10px; +} +.breadcrumb-arrow li a { + position:relative; + border:1px solid #3da8e3; + color:#fff; + background-color:#3da8e3; + text-decoration:none; +} +.breadcrumb-arrow li [class^="icon-"], +.breadcrumb-arrow ul li [class*=" icon-"] { + top: 0; +} +.breadcrumb-arrow-arrow li:first-child a { + padding-left:10px; +} +.breadcrumb-arrow li a:before, +.breadcrumb-arrow li a:after { + position:absolute; + top:0; + content:''; + width: 0; + height: 0; + border-top: 17px solid transparent; + border-bottom: 17px solid transparent; +} +.breadcrumb-arrow li a:before { + right: -10px; + border-left-width: 10px; + border-left-style:solid; + border-left-color:#3da8e3; + z-index:3; +} +.breadcrumb-arrow li a:after{ + right: -11px; + border-left: 10px solid #2980b9; + z-index:2; +} +.breadcrumb-arrow li a:hover, +.breadcrumb-arrow li a:focus { + background-color:#3598ce; + border: 1px solid #3598ce; +} +.breadcrumb-arrow li a:hover:before, +.breadcrumb-arrow li a:focus:before { + border-left-color: #3598ce; +} +.breadcrumb-arrow li a:active { + background-color:#2980b9; + border: 1px solid #2980b9; +} +.breadcrumb-arrow li a:active:before, +.breadcrumb-arrow li a:active:after { + border-left-color:#2980b9; +} +.breadcrumb-arrow li span{ + color:#bdc3c7; +} +/*------------------------------------*\ + $nav-tabs-panel +\*------------------------------------*/ +.nav-tabs-panel, +.nav-tabs-panel.nav-justified { + margin-bottom: 15px; + border-bottom: 1px solid #2986b9; + background-color: #ecf0f1; +} +.nav-tabs-panel .tab-default, +.nav-tabs-panel.nav-justified .tab-default { + margin-right: 0; + padding: 11px 15px; + border-bottom: none; + color: #292929; +} +.nav-tabs-panel.nav-justified .active .tab-default, +.nav-tabs-panel.nav-justified .active .tab-default:hover, +.nav-tabs-panel.nav-justified .active .tab-default:focus, +.nav-tabs-panel .active .tab-default, +.nav-tabs-panel .active .tab-default:hover, +.nav-tabs-panel .active .tab-default:focus { + border-color: transparent transparent #2986b9 transparent; + border-bottom-style:solid; + border-width: 0 0 3px 0; + color: #fff; + background-color: #3da8e3; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.nav-tabs-panel li a:hover, +.nav-tabs-panel li a:focus { + border-color: transparent transparent transparent; + background-color: transparent; +} +.nav-tabs-panel .open .dropdown-toggle, +.nav-tabs-panel li.dropdown.open.active a:hover, +.nav-tabs-panel li.dropdown.open.active a:focus { + color: #292929; + background-color: transparent; + border-color: transparent; +} +.nav-tabs-panel .dropdown-toggle .caret, +.nav-tabs-panel .dropdown-toggle:hover .caret, +.nav-tabs-panel .dropdown-toggle:focus .caret, +.nav-tabs-panel li.dropdown.open .caret, +.nav-tabs-panel li.dropdown.open.active .caret, +.nav-tabs-panel li.dropdown.open a:hover .caret, +.nav-tabs-panel li.dropdown.open a:focus .caret { + border-top-color: #292929; + border-bottom-color: #292929; +} +.nav-tabs-panel .active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff; +} +.nav-tabs-panel .dropdown-menu { + margin-top: 1px; +} +.nav-tabs-panel .dropdown-menu li a { + background-color: transparent; +} +.nav-tabs-panel .dropdown-menu li.active a { + background-color: #2986b9; +} +.nav-tabs-panel .dropdown-menu li a:hover, +.nav-tabs-panel .dropdown-menu li a:focus { + background-color: #2986b9; +} +/*------------------------------------*\ + $tabs-below +\*------------------------------------*/ +.tabs-below .nav-tabs-panel { + margin-top: 15px; + margin-bottom: 0; + border-top: 1px solid #2986b9; + border-bottom:none; +} +.tabs-below .nav-tabs-panel li { + margin-top: 0; +} +.tabs-below .nav-tabs-panel li a:hover, +.tabs-below .nav-tabs-panel li a:focus { + border-top-color: transparent; +} +.tabs-below .nav-tabs-panel .active .tab-default, +.tabs-below .nav-tabs-panel .active .tab-default:hover, +.tabs-below .nav-tabs-panel .active .tab-default:focus { + border-bottom-color: #2986b9; +} +.tabs-below .nav-tabs-panel .dropdown-menu { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +/*------------------------------------*\ + $tabs-left and $tabs-right +\*------------------------------------*/ +.tabs-left .nav-tabs-panel, +.tabs-right .nav-tabs-panel { + position: relative; + border-bottom: none; + z-index: 20; +} +.tabs-left .nav-tabs-panel li, +.tabs-right .nav-tabs-panel li { + float: none; +} +.tabs-left .nav-tabs-panel li .tab-default, +.tabs-right .nav-tabs-panel li .tab-default { + min-width: 39px; + margin-bottom:0; +} +.tabs-left .nav-tabs-panel li .tab-default:hover, +.tabs-left .nav-tabs-panel li .tab-default:focus, +.tabs-right .nav-tabs-panel li .tab-default:hover, +.tabs-right .nav-tabs-panel li .tab-default:focus { + border-color: transparent; +} +.tabs-left .nav-tabs-panel { + float: left; + margin-right: 15px; + border-right: 1px solid #2986b9; +} +.tabs-left .nav-tabs-panel li a { + margin-right: 0; +} +.tabs-left .nav-tabs-panel .active .tab-default, +.tabs-left .nav-tabs-panel .active .tab-default:hover, +.tabs-left .nav-tabs-panel .active .tab-default:focus { + border-color: transparent transparent transparent #2986b9; + border-style: solid; + border-width: 0 0 0 3px; +} +.tabs-right .nav-tabs-panel { + float: right; + margin-left: 15px; + border-left: 1px solid #2986b9; +} +.tabs-right .nav-tabs-panel li a { + margin-left: 0; +} +.tabs-right .nav-tabs-panel .active .tab-default, +.tabs-right .nav-tabs-panel .active .tab-default:hover, +.tabs-right .nav-tabs-panel .active .tab-default:focus { + border-color: transparent #2986b9 transparent transparent; + border-style: solid; + border-width: 0 3px 0 0; +} + + diff --git a/content/css/bootflat-square.css b/content/css/bootflat-square.css new file mode 100644 index 0000000000..0e448ab966 --- /dev/null +++ b/content/css/bootflat-square.css @@ -0,0 +1,69 @@ +/* + Bootflat 1.0.1 + Designed & Built by flathemes, http://www.flathemes.com + Licensed under MIT License, http://opensource.org/licenses/mit-license.html + + Thanks for supporting our website and enjoy! +*/ +/*------------------------------------*\ + $default-square +\*------------------------------------*/ +.img-thumbnail-square, +.btn-square, +.btn-group-square .btn, +.btn-group-square .dropdown-menu, +.btn-group-square .btn, +.btn-group-square .btn:first-child:not(:last-child), +.btn-group-square .btn:last-child:not(:first-child), +.table-bordered-square, +.table-bordered-square tr:first-child th:first-child, +.table-bordered-square tr:first-child th:last-child, +.table-bordered-square tr:last-child td:first-child, +.table-bordered-square tr:last-child td:last-child, +.input-group-square .btn, +.input-group-square .dropdown-menu, +.input-group-square .form-control, +.input-group-square .input-group-addon, +.dropdown-menu-square, +.dropdown-menu-square .dropdown-submenu .dropdown-menu, +.form-square .form-control, +.form-square .btn, +.form-control-square, +.label-square, +.badge-square, +.alert-square, +.alert-square .btn, +.progress-square, +.breadcrumb-square, +.tooltip-square .tooltip-inner, +.popover-square, +.nav-list-panel-square, +.nav-tabs-square li > a, +.tabs-below .nav-tabs-square li > a, +.tabs-right .nav-tabs-square li > a, +.tabs-left .nav-tabs-square li > a, +.nav-tabs-square .dropdown-menu, +.tabs-below .nav-tabs-square .dropdown-menu, +.nav-pills-square li a, +.nav-pills-square .dropdown-menu, +.navbar-square, +.navbar-square .dropdown-menu, +.pagination-square li:first-child a, +.pagination-square li:first-child span, +.pagination-square li:last-child a, +.pagination-square li:last-child span, +.pager-square li a:hover, +.pager-square li a:focus, +.panel-group-square .panel, +.panel-group-square .panel-heading, +.panel-group-square .panel-body, +/*------------------------------------*\ + $extend-square +\*------------------------------------*/ +.breadcrumb-arrow-square li:first-child a { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + + diff --git a/content/css/bootflat.css b/content/css/bootflat.css new file mode 100644 index 0000000000..180823bf12 --- /dev/null +++ b/content/css/bootflat.css @@ -0,0 +1,1560 @@ +/* + Bootflat 1.0.1 + Designed & Built by flathemes, http://www.flathemes.com + Licensed under MIT License, http://opensource.org/licenses/mit-license.html + + Thanks for supporting our website and enjoy! +*/ +/*------------------------------------*\ + $typography +\*------------------------------------*/ +a { + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +a { + color: #2986b9; +} +a:hover { + color: #1b71a0; +} +ins { + background-color: #ff0; + text-decoration: none; +} +dfn[title] { + cursor: help; + border-bottom: 1px dotted; + font-style: normal; +} +q, blockquote { + font-style: italic; +} +q::before { + content: open-quote; +} +q::after { + content: close-quote; +} +hr.hr-line { + display: block; + padding: 0; + border: 0; + border-top: 1px solid #d3d7d7; +} +.first-letter::first-letter { + font-size: 5em; + line-height: 0.8em; + float: left; + position: relative; + padding-right: 6px; + font-weight: normal; +} +/*------------------------------------*\ + $close +\*------------------------------------*/ +.close:hover, .close:focus { + outline: none; +} +/*------------------------------------*\ + $text +\*------------------------------------*/ +.muted { + color: #d3d7d7; +} +a.muted:hover, +a.muted:focus { + color: #aeb1b1; +} +.text-warning { + color: #d7af0d; +} +a.text-warning:hover, +a.text-warning:focus { + color: #b1900b; +} +.text-danger, +.text-error { + color: #c0392b; +} +a.text-danger:hover, +a.text-danger:focus, +a.text-error:hover, +a.text-error:focus { + color: #a5281b; +} +.text-info { + color: #4fbeba; +} +a.text-info:hover, +a.text-info:focus { + color: #1ba5a0; +} +.text-success { + color: #64b92a; +} +a.text-success:hover, +a.text-success:focus { + color: #50a118; +} +.text-inverse { + color: #34495e; +} +a.text-inverse:hover, +a.text-inverse:focus { + color: #263544; +} +/*------------------------------------*\ + $lead +\*------------------------------------*/ +.lead { + margin: 20px 0; + padding: 15px 30px 15px 15px; + border-left: 5px solid #d3d7d7; + font-size: 14px; + background-color: #f9f9f9; +} +/*------------------------------------*\ + $page +\*------------------------------------*/ +.page-header { + margin: 0 0 20px; +} +.page-header h1 { + margin-top: 0; +} +.page-article:before, +.page-article:after { + display: table; + content: " "; +} +.page-article:after { + clear: both; +} +.page-article .meta { + font-size: 12px; + line-height: 18px; + color: #aeb1b1; +} +/*------------------------------------*\ + $thumbnail +\*------------------------------------*/ +a.thumbnail:hover, a.thumbnail:focus { + border-color: #2986b9; +} +.thumbnail .caption { + color: #292929; +} +.thumbnail .caption h1, +.thumbnail .caption h2, +.thumbnail .caption h3 { + margin-top: 9px; + font-size: 16px; + font-weight: bold; +} +/*------------------------------------*\ + $list-group +\*------------------------------------*/ +.list-group-item:hover, +.list-group-item:active { + color: inherit; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + background-color: #2986b9; + border-color: #2986b9; +} +/*------------------------------------*\ + $btn +\*------------------------------------*/ +.btn:focus { + outline: none; +} +.btn, +.btn.disabled, +.btn[disabled] { + border-color: #d3d7d7; + background-color: #d3d7d7; +} +.btn.disabled, +.btn[disabled] { + opacity: .45; + filter: alpha(opacity=45); +} +.btn { + -webkit-transition: border-color 0.3s ease-out, background-color 0.3s ease-out; + -moz-transition: border-color 0.3s ease-out, background-color 0.3s ease-out; + transition: border-color 0.3s ease-out, background-color 0.3s ease-out; + color: #333; +} +.btn:hover, +.btn:focus, +.btn:active, +.btn.active { + border-color: #aeb1b1; + background-color: #aeb1b1; +} +.btn-link { + border: 1px solid transparent !important; + color: #2986b9; + background-color: transparent; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.btn-link.btn-lg { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} +.btn-link.btn-sm, +.btn-link.btn-xs { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +.btn-link:hover, +.btn-link:focus { + text-decoration: none; +} +.btn-link:hover, +.btn-link:focus, +.btn-link:active, +.btn-link.active { + color: #333; + border-color: #d3d7d7; + background-color: #d3d7d7; +} +.btn-link.disabled, +.btn-link[disabled] { + border-color: #d3d7d7; + background-color: #d3d7d7; + color: #333; +} +.btn-default { + margin-left: 0; + /*border: 1px solid #ddd !important;*/ + background-color: #fff; +} +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + border-color: #aeb1b1; + background-color: #d3d7d7; +} +.btn-default.disabled, +.btn-default[disabled] { + background-color: #fff; +} +.btn-primary, +.btn-info, +.btn-success, +.btn-warning, +.btn-danger, +.btn-inverse { + color: #fff; +} +.btn-primary, +.btn-primary.disabled, +.btn-primary[disabled] { + border-color: #2986b9; + background-color: #2986b9; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + border-color: #1b71a0; + background-color: #1b71a0; +} +.btn-info, +.btn-info.disabled, +.btn-info[disabled] { + border-color: #4fbeba; + background-color: #4fbeba; +} +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + border-color: #1ba5a0; + background-color: #1ba5a0; +} +.btn-success, +.btn-success.disabled, +.btn-success[disabled] { + border-color: #64b92a; + background-color: #64b92a; +} +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + border-color: #50a118; + background-color: #50a118; +} +.btn-warning, +.btn-warning.disabled, +.btn-warning[disabled] { + border-color: #d7af0d; + background-color: #d7af0d; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + border-color: #b1900b; + background-color: #b1900b; +} +.btn-danger, +.btn-danger.disabled, +.btn-danger[disabled] { + border-color: #c0392b; + background-color: #c0392b; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + border-color: #a5281b; + background-color: #a5281b; +} +.btn-inverse, +.btn-inverse.disabled, +.btn-inverse[disabled] { + border-color: #34495e; + background-color: #34495e; + color: #fff; +} +.btn-inverse:hover, +.btn-inverse:focus, +.btn-inverse:active, +.btn-inverse.active +.open .dropdown-toggle.btn-inverse { + border-color: #263544; + background-color: #263544; + color: #fff; +} +.btn-inverse .caret { + border-top-color: #fff; +} +.dropup .btn-inverse .caret { + border-bottom-color: #fff; +} +/*------------------------------------*\ + $btn-group +\*------------------------------------*/ +.btn-group .btn { + border-left-color: #aeb1b1; + border-right-color: #aeb1b1; +} +.btn-group .btn:first-child { + border-left-color: #d3d7d7; +} +.btn-group .btn:last-child, +.btn-group .btn + .dropdown-toggle { + border-right-color: #d3d7d7; +} +.btn-group-vertical .btn:first-child { + border-top-color: #d3d7d7; +} +.btn-group-vertical .btn:last-child { + border-bottom-color: #d3d7d7; +} +.btn-group-vertical .btn, +.btn-group-vertical .btn-group .btn { + border-top-color: #aeb1b1; + border-bottom-color: #aeb1b1; +} +.btn-group .btn-default { + border-left-color: #d3d7d7; + border-right-color: #d3d7d7; +} +.btn-group .btn-default:hover, +.btn-group .btn-default:focus, +.btn-group .btn-default:active, +.btn-group .btn-default.active, +.btn-group-vertical .btn-default:hover, +.btn-group-vertical .btn-default:focus, +.btn-group-vertical .btn-default:active, +.btn-group-vertical .btn-default.active { + border-top-color: #d3d7d7; + border-bottom-color: #d3d7d7; +} +.btn-group-vertical .btn-default, +.btn-group-vertical .btn-group .btn-default, +.btn-group-vertical .btn-default { + border-top-color: #d3d7d7 !important; + border-bottom-color: #d3d7d7; +} +.btn-group .btn-primary { + border-left-color: #1b71a0; + border-right-color: #1b71a0; +} +.btn-group .btn-primary:first-child { + border-left-color: #2986b9; +} +.btn-group .btn-primary:last-child, +.btn-group .btn-primary + .dropdown-toggle { + border-right-color: #2986b9; +} +.btn-group-vertical .btn-primary:first-child { + border-top-color: #1b71a0; +} +.btn-group-vertical .btn-primary, +.btn-group-vertical .btn-group .btn-primary, +.btn-group-vertical .btn-primary:last-child { + border-bottom-color: #2986b9; +} +.btn-group-vertical .btn-primary { + border-top-color: #1b71a0; + border-bottom-color: #1b71a0; +} +.btn-group .btn-info { + border-left-color: #1ba5a0; + border-right-color: #1ba5a0; +} +.btn-group .btn-info:first-child { + border-left-color: #4fbeba; +} +.btn-group .btn-info:last-child, +.btn-group .btn-info + .dropdown-toggle { + border-right-color: #4fbeba; +} +.btn-group-vertical .btn-info:first-child { + border-top-color: #1ba5a0; +} +.btn-group-vertical .btn-info, +.btn-group-vertical .btn-group .btn-info, +.btn-group-vertical .btn-info:last-child { + border-bottom-color: #4fbeba; +} +.btn-group-vertical .btn-info { + border-top-color: #1ba5a0; + border-bottom-color: #1ba5a0; +} +.btn-group .btn-success { + border-left-color: #50a118; + border-right-color: #50a118; +} +.btn-group .btn-success:first-child { + border-left-color: #64b92a; +} +.btn-group .btn-success:last-child, +.btn-group .btn-success + .dropdown-toggle { + border-right-color: #64b92a; +} +.btn-group-vertical .btn-success:first-child { + border-top-color: #50a118; +} +.btn-group-vertical .btn-success, +.btn-group-vertical .btn-group .btn-success, +.btn-group-vertical .btn-success:last-child { + border-bottom-color: #64b92a; +} +.btn-group-vertical .btn-success { + border-top-color: #50a118; + border-bottom-color: #50a118; +} +.btn-group .btn-warning { + border-left-color: #b1900b; + border-right-color: #b1900b; +} +.btn-group .btn-warning:first-child { + border-left-color: #d7af0d; +} +.btn-group .btn-warning:last-child, +.btn-group .btn-warning + .dropdown-toggle { + border-right-color: #d7af0d; +} +.btn-group-vertical .btn-warning:first-child { + border-top-color: #b1900b; +} +.btn-group-vertical .btn-warning, +.btn-group-vertical .btn-group .btn-warning, +.btn-group-vertical .btn-warning:last-child { + border-bottom-color: #d7af0d; +} +.btn-group-vertical .btn-warning { + border-top-color: #b1900b; + border-bottom-color: #b1900b; +} +.btn-group .btn-danger { + border-left-color: #a5281b; + border-right-color: #a5281b; +} +.btn-group .btn-danger:first-child { + border-left-color: #c0392b; +} +.btn-group .btn-danger:last-child, +.btn-group .btn-danger + .dropdown-toggle { + border-right-color: #c0392b; +} +.btn-group-vertical .btn-danger:first-child { + border-top-color: #a5281b; +} +.btn-group-vertical .btn-danger, +.btn-group-vertical .btn-group .btn-danger, +.btn-group-vertical .btn-danger:last-child { + border-bottom-color: #c0392b; +} +.btn-group-vertical .btn-danger { + border-top-color: #a5281b; + border-bottom-color: #a5281b; +} +.btn-group .btn-inverse { + border-left-color: #2c3e50; + border-right-color: #2c3e50; +} +.btn-group .btn-inverse:first-child { + border-left-color: #34495e; +} +.btn-group .btn-inverse:last-child, +.btn-group .btn-inverse + .dropdown-toggle { + border-right-color: #34495e; +} +.btn-group-vertical .btn-inverse:first-child { + border-top-color: #2c3e50; +} +.btn-group-vertical .btn-inverse, +.btn-group-vertical .btn-group .btn-inverse, +.btn-group-vertical .btn-inverse:last-child { + border-bottom-color: #34495e; +} +.btn-group-vertical .btn-inverse { + border-top-color: #2c3e50; + border-bottom-color: #2c3e50; +} +/*------------------------------------*\ + $btn-group-justified +\*------------------------------------*/ +.btn-group-justified .btn { + border-right: none; +} +/*------------------------------------*\ + $input-group-btn +\*------------------------------------*/ +.input-group-btn .btn + .btn { + border-left: 1px solid #aeb1b1; +} +.input-group-btn .btn + .btn.btn-default { + margin-left: -5px; + border-left: 1px solid #d3d7d7; +} +.input-group-btn .btn + .btn.btn-primary { + border-left: 1px solid #1b71a0; +} +.input-group-btn .btn + .btn.btn-info { + border-left: 1px solid #1ba5a0; +} +.input-group-btn .btn + .btn.btn-success { + border-left: 1px solid #50a118; +} +.input-group-btn .btn + .btn.btn-warning { + border-left: 1px solid #b1900b; +} +.input-group-btn .btn + .btn.btn-danger { + border-left: 1px solid #a5281b; +} +.input-group-btn .btn + .btn.btn-inverse { + border-left: 1px solid #263544; +} +/*------------------------------------*\ + $dropdown-menu +\*------------------------------------*/ +.dropdown-menu { + border: none; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + background-color: #292929; +} +.dropdown-menu .dropdown-header { + font-size: 14px; + font-weight: bold; + padding: 5px 20px; +} +.dropdown-menu li a { + padding:5px 20px; + color: #fff; +} +.dropdown-menu li a:hover, +.dropdown-menu li a:focus, +.dropdown-menu .active a, +.dropdown-menu .active a:hover, +.dropdown-menu .active a:focus{ + background-color: #2986b9; + -webkit-transition: 0.25s; + -moz-transition: 0.25s; + transition: 0.25s; + -webkit-backface-visibility: hidden; + outline: none; +} +.dropdown-menu .disabled a, +.dropdown-menu .disabled a:hover, +.dropdown-menu .disabled a:focus { + color:#9B9B9B !important; + cursor: default; +} +.dropdown-menu .divider { + margin:3px 0 0; + background-color: #373737; + border-bottom: none; +} +/*------------------------------------*\ + $dropdown-submenu +\*------------------------------------*/ +.dropdown-submenu { + position: relative; +} +.dropdown-submenu .dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 4px; + -moz-border-radius: 0 4px 4px 4px; + border-radius: 0 4px 4px 4px; +} +.dropdown-submenu:hover .dropdown-menu { + display: block; +} +.dropup .dropdown-submenu .dropdown-menu { + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -2px; + -webkit-border-radius: 4px 4px 4px 0; + -moz-border-radius: 4px 4px 4px 0; + border-radius: 4px 4px 4px 0; +} +.dropdown-submenu > a:after { + display: block; + content: " "; + float: right; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 5px 0 5px 5px; + border-left-color: #fff; + margin-top: 5px; + margin-right: -10px; +} +.dropdown-submenu:hover a:after { + border-left-color: #ffffff; +} +.dropdown-submenu.pull-left { + float: none; +} +.dropdown-submenu.pull-left .dropdown-menu { + left: -100%; + margin-left: 10px; + -webkit-border-radius: 4px 0 4px 4px; + -moz-border-radius: 4px 0 4px 4px; + border-radius: 4px 0 4px 4px; +} +/*------------------------------------*\ + $table +\*------------------------------------*/ +.table { + background-color: #fff; + border-collapse: separate; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.table .success td, +.table .danger td, +.table .warning td, +.table .info td, +.table .active td { + color: #fff; +} +.table .success th, +.table .success td { + border-color: #64b92a !important; + background-color: #64b92a !important; +} +.table .danger th, +.table .danger td { + border-color: #c0392b !important; + background-color: #c0392b !important; +} +.table .warning th, +.table .warning td { + border-color: #d7af0d !important; + background-color: #d7af0d !important; +} +.table .info th, +.table .info td { + border-color: #4fbeba !important; + background-color: #4fbeba !important; +} +.table .active th, +.table .active td { + border-color: #2986b9 !important; + background-color: #2986b9 !important; +} +.table-background thead { + color:#fff; + background-color:#d3d7d7; +} +.table-background thead tr th, +.table-background thead tr td { + border-bottom: none; +} +.table-bordered tr:first-child th:first-child { + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-left-radius: 4px; +} +.table-bordered tr:first-child th:last-child { + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; + border-top-right-radius: 4px; +} +.table-bordered tr:last-child td:first-child { + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + border-bottom-left-radius: 4px; +} +.table-bordered tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + border-bottom-right-radius: 4px; +} +.table-bordered { + border-width: 1px 1px 0 0; +} +.table-bordered thead tr th, +.table-bordered tbody tr th, +.table-bordered tfoot tr th, +.table-bordered thead tr td, +.table-bordered tbody tr td, +.table-bordered tfoot tr td { + border-width: 0 0 1px 1px; +} +.table-hover tbody tr td, +.table-hover tbody tr th { + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; +} +.table-hover tbody tr:hover td, +.table-hover tbody tr:hover th, +.table-striped tbody tr:nth-child(odd) td, +.table-striped tbody tr:nth-child(odd) th { + background-color: #ecf0f1; +} +.table-hover tbody tr:hover td, +.table-hover tbody tr:hover th { + background-color: #f9f9f9; +} +.table-hover .success:hover td, +.table-hover .success:hover th { + border-color: #79d738 !important; + background-color: #79d738 !important; +} +.table-hover .danger:hover td, +.table-hover .danger:hover th { + border-color: #d44637 !important; + background-color: #d44637 !important; +} +.table-hover .warning:hover td, +.table-hover .warning:hover th { + border-color: #f1c40f !important; + background-color: #f1c40f !important; +} +.table-hover .info:hover td, +.table-hover .info:hover th { + border-color: #4cd1cb !important; + background-color: #4cd1cb !important; +} +.table-hover .active:hover td, +.table-hover .active:hover th { + border-color: #3598ce !important; + background-color: #3598ce !important; +} +/*------------------------------------*\ + $form +\*------------------------------------*/ +.form-control { + padding: 4px 6px; + border-width: 1px; + border-style: solid; + border-color: #ddd #eee #eee #ddd; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.form-control:-moz-placeholder, +.form-control::-moz-placeholder, +.form-control:-ms-input-placeholder, +.form-control::-webkit-input-placeholder, +.form-control.placeholder { + color: #bdc3c7; +} +.form-control:focus { + -webkit-transition: 0.25s; + -moz-transition: 0.25s; + transition: 0.25s; + -webkit-backface-visibility: hidden; + outline:none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + opacity: 0.4; + filter: alpha(opacity=4); +} + +.form-inline .form-group, +.form-inline .checkbox, +.form-inline .radio, +.form-inline .btn { + margin-right: 5px; +} +/*------------------------------------*\ + $validation states +\*------------------------------------*/ +.has-warning .form-control, +.has-warning .form-control:focus, +.has-error .form-control, +.has-error .form-control:focus, +.has-info .form-control, +.has-info .form-control:focus, +.has-success .form-control, +.has-success .form-control:focus { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + border-radius: auto; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .form-control { + color: #d7af0d; +} +.has-warning .form-control { + border-color:#d7af0d; +} +.has-error .help-block, +.has-error .control-label, +.has-error .form-control { + color: #c0392b; +} +.has-error .form-control { + border-color: #c0392b; +} +.has-info .help-block, +.has-info .control-label, +.has-info .form-control { + color: #4fbeba; +} +.has-info .form-control { + border-color: #4fbeba; +} +.has-success .help-block, +.has-success .control-label, +.has-success .form-control { + color: #64b92a; +} +.has-success .form-control { + border-color:#64b92a; +} +/*------------------------------------*\ + $input-group-addon +\*------------------------------------*/ +.input-group-addon { + background-color: #d3d7d7; + border: 1px solid #d3d7d7; +} +.input-group-addon .radio, +.input-group-addon .checkbox { + margin: -2px 0 -4px !important; +} +/*------------------------------------*\ + $search-query +\*------------------------------------*/ +.form-search .search-query, +.form-search .search-query:first-child, +.form-search .search-query:last-child { + padding: 0 17px; + -webkit-border-radius: 17px; + -moz-border-radius: 17px; + border-radius: 17px; +} +.input-group .form-control:last-child { + padding: 0 17px 0 10px; + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group .form-control:first-child { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.form-search .btn { + -webkit-border-radius: 25px; + -moz-border-radius: 25px; + border-radius: 25px; +} +.search-only { + position: relative; +} +.search-only:before { + position: absolute; + top: 1px; + left: 8px; + width: 30px; + line-height: 30px; + text-align: center; + font-family: "FontAwesome"; + font-size: 18px; + color: #d3d7d7; + content: "\f002"; + z-index: 20; +} +.search-only .form-control:last-child { + padding-left: 40px; +} +/*------------------------------------*\ + $radio and $checkbox +\*------------------------------------*/ +.radio, .checkbox { + padding-left:0; + margin-top: 0; +} +.checkbox label, +.radio label{ + display:inline-block; + vertical-align:top; + height:24px; + line-height:24px; + font-weight: normal; + cursor:pointer; +} +.checkbox .icheckbox_flat, +.radio .iradio_flat{ + background-image: url(../img/check_flat/default.png); +} +.checkbox .icheckbox_flat, +.radio .iradio_flat{ + display:inline-block; + vertical-align:top; + margin: 0; + padding: 0; + width: 24px; + height: 24px; + border: none; + cursor: pointer; + background-repeat:no-repeat; +} +.checkbox .icheckbox_flat { + background-position: 0 0; +} +.checkbox .icheckbox_flat.hover { + background-position: -24px 0; +} +.checkbox .icheckbox_flat.checked { + background-position: -48px 0; +} +fieldset[disabled] .checkbox .icheckbox_flat, +.checkbox .icheckbox_flat.disabled { + background-position: -72px 0; + cursor: not-allowed; +} +.checkbox .icheckbox_flat.checked.disabled { + background-position: -96px 0; +} +.radio .iradio_flat { + background-position: -120px 0; +} +.radio .iradio_flat.hover { + background-position: -144px 0; +} +.radio .iradio_flat.checked { + background-position: -168px 0; +} +fieldset[disabled] .radio .iradio_flat, +.radio .iradio_flat.disabled { + background-position: -192px 0; + cursor: not-allowed; +} +.radio .iradio_flat.checked.disabled { + background-position: -216px 0; +} +fieldset[disabled] .checkbox, +fieldset[disabled] .radio, +.checkbox .disabled, +.checkbox .checked.disabled, +.radio .disabled, +.radio .checked.disabled { + color:#bdc3c7; + cursor: not-allowed; +} +.radio-inline { + margin-left: 10px; +} +/*------------------------------------*\ + $label and $badge +\*------------------------------------*/ +.label, .badge { + background-color: #d3d7d7; +} +.label.label-primary, +.badge.badge-primary, +.label.label-info, +.badge.badge-info, +.label.label-success, +.badge.badge-success, +.label.label-warning, +.badge.badge-warning, +.label.label-danger, +.badge.badge-danger, +.label.label-inverse, +.badge.badge-inverse { + color: #fff; +} +.label.label-primary, +.badge.badge-primary { + background-color: #2986b9; +} +.label.label-info, +.badge.badge-info { + background-color: #4fbeba; +} +.label.label-success, +.badge.badge-success { + background-color: #64b92a; +} +.label.label-warning, +.badge.badge-warning { + background-color: #d7af0d; +} +.label.label-danger, +.badge.badge-danger { + background-color: #c0392b; +} +.label.label-inverse, +.badge.badge-inverse { + background-color: #34495e; +} +/*------------------------------------*\ + $alert +\*------------------------------------*/ +.alert { + background-color: #fece10; + border: 1px solid #fece10; +} +.alert, .alert h4{ + color: #FFF; +} +.alert .alert-link, +.alert .alert-link:hover, +.alert .alert-link:focus { + color: #000; + opacity: 0.55; + filter: alpha(opacity=55); +} +.alert h4{ + margin-bottom: 10px; + font-weight: bold; +} +.alert-dismissable .close { + color: #000; +} +.alert.alert-info { + background-color: #5eddd8; + border: 1px solid #5eddd8; +} +.alert.alert-danger, +.alert.alert-error { + background-color: #e74c3c; + border: 1px solid #e74c3c; +} +.alert.alert-success { + background-color: #87eb41; + border: 1px solid #87eb41; +} +/*------------------------------------*\ + $popover +\*------------------------------------*/ +.popover { + background-color: #292929; + color:#FFF; + border: 1px solid #292929; +} +.popover-title { + padding-bottom: 0; + font-weight: bold; + background-color: transparent; + border-bottom: none; +} +.popover .close { + position: absolute; + top:10px; + right: 10px; +} +.popover.top .arrow, +.popover.top .arrow:after { + border-top-color: #292929; +} +.popover.right .arrow, +.popover.right .arrow:after { + border-right-color: #292929; +} +.popover.bottom .arrow, +.popover.bottom .arrow:after { + border-bottom-color: #292929; +} +.popover.left .arrow, +.popover.left .arrow:after { + border-left-color: #292929; +} +/*------------------------------------*\ + $pagination +\*------------------------------------*/ +.pagination .active a, +.pagination .active span, +.pagination .active a:hover, +.pagination .active span:hover, +.pagination .active a:focus, +.pagination .active span:focus { + background-color: #2986b9; + border-color: #2986b9; +} +/*------------------------------------*\ + $pager +\*------------------------------------*/ +.pager li a, .pager li span { + border: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.pager li a:hover, +.pager li a:focus { + color: #fff; + background-color: #2986b9; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +/*------------------------------------*\ + $progress +\*------------------------------------*/ +.progress, +.progress .progress-bar { + -webkit-box-shadow: none !important; + -moz-box-shadow: none !important; + box-shadow: none !important; +} +.progress { + height: 12px; + overflow: hidden; + background-color: #ecf0f1; +} +.progress .progress-bar { + background-color: #2986b9; +} +.progress-success .progress-bar, +.progress .progress-bar-success, +.progress-success.progress-striped .progress-bar, +.progress-striped .progress-bar-success { + background-color: #64b92a; +} +.progress-info .progress-bar, +.progress .progress-bar-info, +.progress-info.progress-striped .progress-bar, +.progress-striped .progress-bar-info { + background-color: #4fbeba; +} +.progress-danger .progress-bar, +.progress .progress-bar-danger, +.progress-danger.progress-striped .progress-bar, +.progress-striped .progress-bar-danger { + background-color: #c0392b; +} +.progress-warning .progress-bar, +.progress .progress-bar-warning, +.progress-warning.progress-striped .progress-bar, +.progress-striped .progress-bar-warning { + background-color: #d7af0d; +} +/*------------------------------------*\ + $breadcrumb +\*------------------------------------*/ +.breadcrumb { + background-color: #ecf0f1; +} +/*------------------------------------*\ + $nav +\*------------------------------------*/ +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + border-color: transparent; +} +/*------------------------------------*\ + $navbar-toggle +\*------------------------------------*/ +.navbar-toggle:focus { + outline: none; +} +/*------------------------------------*\ + $navbar +\*------------------------------------*/ +.navbar .divider-vertical { + border-left-width: 1px; + border-left-style: solid; + height: 50px; +} +.navbar-default { + border:none; + background-color:#3da8e3; +} +.navbar-default .navbar-brand { + color: #fff; +} +.navbar-default .navbar-link:hover, +.navbar-default .navbar-link:focus, +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #d3efff; +} +.navbar-default .navbar-link, +.navbar-default .navbar-text { + color: #d3efff; +} +.navbar-default .dropdown-header { + color: #aeb1b1; +} +.navbar-default .divider-vertical { + border-left-color: #2986b9; +} +.navbar-default .nav li a, +.navbar-default .nav li a:focus, +.navbar-default .nav li a:hover { + color: #fff; +} +.navbar-default .nav .active a, +.navbar-default .nav .active a:hover, +.navbar-default .nav .active a:focus { + color: #fff; + background-color: #2986b9; +} +.navbar-default .nav li.dropdown.open .dropdown-toggle, +.navbar-default .nav li.dropdown.active .dropdown-toggle, +.navbar-default .nav li.dropdown.open.active .dropdown-toggle { + background-color: #2986b9; + color: #fff; +} +.navbar-default .nav li.dropdown a:hover .caret, +.navbar-default .nav li.dropdown a:focus .caret, +.navbar-default .nav li.dropdown .dropdown-toggle .caret, +.navbar-default .nav li.dropdown.open .dropdown-toggle .caret, +.navbar-default .nav li.dropdown.active .dropdown-toggle .caret, +.navbar-default .nav li.dropdown.open.active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff; +} +.navbar-default .nav li .dropdown-menu:before, +.navbar-default .nav li .dropdown-menu:after { + border-bottom-color: transparent; +} +.navbar-default .navbar-toggle { + background-color: #aeb1b1; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #c2c2c2; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #aeb1b1; +} +/*------------------------------------*\ + $navbar-inverse +\*------------------------------------*/ +.navbar-inverse { + background-color:#292929; +} +.navbar-inverse .nav .active a, +.navbar-inverse .nav .active a:hover, +.navbar-inverse .nav .active a:focus, +.navbar-inverse .nav li.dropdown.open .dropdown-toggle, +.navbar-inverse .nav li.dropdown.active .dropdown-toggle, +.navbar-inverse .nav li.dropdown.open.active .dropdown-toggle{ + background-color: #000; +} +.navbar-inverse .divider-vertical { + border-left-color: #000; +} +.navbar-inverse .navbar-form .form-control { + border: 1px solid #292929; +} +.navbar-inverse .navbar-form .form-control:focus, +.navbar-inverse .navbar-form .form-control.focused { + color: #292929; + background-color: #fff !important; + border: 1px solid #000; +} +/*------------------------------------*\ + $navbar-right +\*------------------------------------*/ +.navbar-right .dropdown.open .dropdown-toggle { + -webkit-border-radius: 0 4px 0 0; + -moz-border-radius: 0 4px 0 0; + border-radius: 0 4px 0 0; +} +/*------------------------------------*\ + $nav-list +\*------------------------------------*/ +.nav-list { + padding: 10px 0; +} +.nav-list li a, +.nav-list .nav-header { + padding: 5px 15px; +} +.nav-list .nav-header { + font-weight: bold; +} +.nav-list li a { + color: #292929; +} +.nav-list li a:hover, +.nav-list li a:focus, +.nav-list .active a, +.nav-list .active a:hover, +.nav-list .active a:focus { + color: #3498db; + text-decoration: none; +} +.nav-list li a:hover, +.nav-list li a:focus { + background-color: transparent; +} +.nav-list .active a, +.nav-list .active a:hover, +.nav-list .active a:focus { + font-weight: bold; +} +.nav-list .divider { + margin: 9px 15px; + overflow: hidden; + border-bottom: 1px solid #ddd; +} +.nav-list .nav-list-sub { + list-style: none; +} +.nav-list .nav-list-sub { + padding-left: 0; +} +.nav-list .nav-list-sub li a { + padding: 2px 15px 2px 30px; + display: block; +} + +.nav-list-panel { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + background-color:#ecf0f1; +} +.nav-list-panel li a:hover, +.nav-list-panel li a:focus, +.nav-list-panel .active a, +.nav-list-panel .active a:hover, +.nav-list-panel .active a:focus { + color: #fff; + background-color: #2986b9; + text-decoration: none; +} +.nav-list-panel li a:hover, +.nav-list-panel li a:focus { + opacity: 0.45; + filter: alpha(opacity=45); +} +.nav-list-panel .active a, +.nav-list-panel .active a:hover, +.nav-list-panel .active a:focus { + opacity: 1; + filter: alpha(opacity=100); +} +/*------------------------------------*\ + $nav-tabs +\*------------------------------------*/ +.nav-tabs > li > a { + color: #292929; +} +.nav-tabs .dropdown-toggle .caret, +.nav-tabs .dropdown-toggle:hover .caret, +.nav-tabs .dropdown-toggle:focus .caret, +.nav-tabs li.dropdown.open .caret, +.nav-tabs li.dropdown.open.active .caret, +.nav-tabs li.dropdown.open a:hover .caret, +.nav-tabs li.dropdown.open a:focus .caret, +.nav-tabs .active .dropdown-toggle .caret { + border-top-color: #292929; + border-bottom-color: #292929; +} +.tabs-below .nav-tabs { + border-top: 1px solid #ddd; + border-bottom: none; +} +.tabs-below .nav-tabs .dropdown-menu { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.tabs-below .nav-tabs li { + margin-top: -1px; + margin-bottom: 0; +} +.tabs-below .nav-tabs li a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} +.tabs-below .nav-tabs li a:hover, +.tabs-below .nav-tabs li a:focus { + border-top-color: #ddd; + border-bottom-color: transparent; +} +.tabs-below .nav-tabs .active a, +.tabs-below .nav-tabs .active a:hover, +.tabs-below .nav-tabs .active a:focus { + border-color: transparent #ddd #ddd #ddd; +} +.tabs-left .nav-tabs, +.tabs-right .nav-tabs { + border-bottom: none; +} +.tabs-left .nav-tabs li, +.tabs-right .nav-tabs li { + float: none; +} +.tabs-left .nav-tabs li a, +.tabs-right .nav-tabs li a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; +} +.tabs-left .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} +.tabs-left .nav-tabs li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} +.tabs-left .nav-tabs li a:hover, +.tabs-left .nav-tabs li a:focus { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} +.tabs-left .nav-tabs .active a, +.tabs-left .nav-tabs .active a:hover, +.tabs-left .nav-tabs .active a:focus { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #ffffff; +} +.tabs-right .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} +.tabs-right .nav-tabs li a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} +.tabs-right .nav-tabs li a:hover, +.tabs-right .nav-tabs li a:focus { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} +.tabs-right .nav-tabs .active a, +.tabs-right .nav-tabs .active a:hover, +.tabs-right .nav-tabs .active a:focus { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} +/*------------------------------------*\ + $nav-pills +\*------------------------------------*/ +.nav-pills > li > a { + color: #292929; +} +.nav-pills > li > a:hover, +.nav-pills > li > a:focus { + background-color: ; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + background-color: #2986b9; + color:#fff; +} +.nav-pills .dropdown-toggle .caret, +.nav-pills .open .dropdown-toggle:focus .caret, +.nav-pills .dropdown-toggle:hover .caret, +.nav-pills .dropdown-toggle:focus .caret { + border-top-color: #292929; + border-bottom-color: #292929; +} +.nav-pills .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle:focus { + background-color: transparent; +} +/*------------------------------------*\ + $breadcrumb +\*------------------------------------*/ +.breadcrumb > li + li::before { + font-family: 'FontAwesome'; + content: "\f105"; +} +/*------------------------------------*\ + $panel-group +\*------------------------------------*/ +.panel-group .panel { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} +.panel-group .panel-heading { + padding: 9px 15px; + background-color: #2986b9; +} +.panel-group .panel-heading a, +.panel-group .panel-heading a:hover, +.panel-group .panel-heading a:focus, +.panel-group .panel-heading a:active { + color:#fff; + text-decoration: none; +} +.panel-group .panel-body { + border: 1px solid #ddd; + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + diff --git a/content/css/font-awesome.min.css b/content/css/font-awesome.min.css new file mode 100644 index 0000000000..7b8ed50e9d --- /dev/null +++ b/content/css/font-awesome.min.css @@ -0,0 +1,405 @@ +@font-face{font-family:'FontAwesome';src:url('../font/fontawesome-webfont-eot.eot?v=3.2.1');src:url('../font/fontawesome-webfont-eot.eot?#iefix&v=3.2.1') format('embedded-opentype'),url('../font/fontawesome-webfont-woff.woff?v=3.2.1') format('woff'),url('../font/fontawesome-webfont-ttf.ttf?v=3.2.1') format('truetype'),url('../font/fontawesome-webfont-svg.svg#fontawesomeregular?v=3.2.1') format('svg');font-weight:normal;font-style:normal;}[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;} +[class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none;} +.icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em;} +a [class^="icon-"],a [class*=" icon-"]{display:inline;} +[class^="icon-"].icon-fixed-width,[class*=" icon-"].icon-fixed-width{display:inline-block;width:1.1428571428571428em;text-align:right;padding-right:0.2857142857142857em;}[class^="icon-"].icon-fixed-width.icon-large,[class*=" icon-"].icon-fixed-width.icon-large{width:1.4285714285714286em;} +.icons-ul{margin-left:2.142857142857143em;list-style-type:none;}.icons-ul>li{position:relative;} +.icons-ul .icon-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;text-align:center;line-height:inherit;} +[class^="icon-"].hide,[class*=" icon-"].hide{display:none;} +.icon-muted{color:#eeeeee;} +.icon-light{color:#ffffff;} +.icon-dark{color:#333333;} +.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;} +.icon-5x{font-size:5em;}.icon-5x.icon-border{border-width:5px;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px;} +.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;} +[class^="icon-"],[class*=" icon-"]{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;} +.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;} +.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-"],.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;} +.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;} +.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{line-height:inherit;} +.icon-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:-35%;}.icon-stack [class^="icon-"],.icon-stack [class*=" icon-"]{display:block;text-align:center;position:absolute;width:100%;height:100%;font-size:1em;line-height:inherit;*line-height:2em;} +.icon-stack .icon-stack-base{font-size:2em;*line-height:1em;} +.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;} +a .icon-stack,a .icon-spin{display:inline-block;text-decoration:none;} +@-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);}}.icon-rotate-90:before{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);} +.icon-rotate-180:before{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);} +.icon-rotate-270:before{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);} +.icon-flip-horizontal:before{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1);} +.icon-flip-vertical:before{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1);} +a .icon-rotate-90:before,a .icon-rotate-180:before,a .icon-rotate-270:before,a .icon-flip-horizontal:before,a .icon-flip-vertical:before{display:inline-block;} +.icon-glass:before{content:"\f000";} +.icon-music:before{content:"\f001";} +.icon-search:before{content:"\f002";} +.icon-envelope-alt: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-power-off:before,.icon-off:before{content:"\f011";} +.icon-signal:before{content:"\f012";} +.icon-gear:before,.icon-cog:before{content:"\f013";} +.icon-trash:before{content:"\f014";} +.icon-home:before{content:"\f015";} +.icon-file-alt: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-rotate-right:before,.icon-repeat:before{content:"\f01e";} +.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-mail-forward:before,.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-gears:before,.icon-cogs:before{content:"\f085";} +.icon-comments:before{content:"\f086";} +.icon-thumbs-up-alt:before{content:"\f087";} +.icon-thumbs-down-alt: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-unchecked:before,.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-wiki:before{content:"\f109";} +.icon-releases:before{content:"\f01a";} +.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-paperclip:before,.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:before{content:"\f0e0";} +.icon-linkedin:before{content:"\f0e1";} +.icon-rotate-left:before,.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-text-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-mail-reply:before,.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";} +.icon-expand-alt:before{content:"\f116";} +.icon-collapse-alt:before{content:"\f117";} +.icon-smile:before{content:"\f118";} +.icon-frown:before{content:"\f119";} +.icon-meh:before{content:"\f11a";} +.icon-gamepad:before{content:"\f11b";} +.icon-keyboard:before{content:"\f11c";} +.icon-flag-alt:before{content:"\f11d";} +.icon-flag-checkered:before{content:"\f11e";} +.icon-terminal:before{content:"\f120";} +.icon-code:before{content:"\f121";} +.icon-reply-all:before{content:"\f122";} +.icon-mail-reply-all:before{content:"\f122";} +.icon-star-half-full:before,.icon-star-half-empty:before{content:"\f123";} +.icon-location-arrow:before{content:"\f124";} +.icon-crop:before{content:"\f125";} +.icon-code-fork:before{content:"\f126";} +.icon-unlink:before{content:"\f127";} +.icon-question:before{content:"\f128";} +.icon-info:before{content:"\f129";} +.icon-exclamation:before{content:"\f12a";} +.icon-superscript:before{content:"\f12b";} +.icon-subscript:before{content:"\f12c";} +.icon-eraser:before{content:"\f12d";} +.icon-puzzle-piece:before{content:"\f12e";} +.icon-microphone:before{content:"\f130";} +.icon-microphone-off:before{content:"\f131";} +.icon-shield:before{content:"\f132";} +.icon-calendar-empty:before{content:"\f133";} +.icon-fire-extinguisher:before{content:"\f134";} +.icon-rocket:before{content:"\f135";} +.icon-maxcdn:before{content:"\f136";} +.icon-chevron-sign-left:before{content:"\f137";} +.icon-chevron-sign-right:before{content:"\f138";} +.icon-chevron-sign-up:before{content:"\f139";} +.icon-chevron-sign-down:before{content:"\f13a";} +.icon-html5:before{content:"\f13b";} +.icon-css3:before{content:"\f13c";} +.icon-anchor:before{content:"\f13d";} +.icon-unlock-alt:before{content:"\f13e";} +.icon-bullseye:before{content:"\f140";} +.icon-ellipsis-horizontal:before{content:"\f141";} +.icon-ellipsis-vertical:before{content:"\f142";} +.icon-rss-sign:before{content:"\f143";} +.icon-play-sign:before{content:"\f144";} +.icon-ticket:before{content:"\f145";} +.icon-minus-sign-alt:before{content:"\f146";} +.icon-check-minus:before{content:"\f147";} +.icon-level-up:before{content:"\f148";} +.icon-level-down:before{content:"\f149";} +.icon-check-sign:before{content:"\f14a";} +.icon-edit-sign:before{content:"\f14b";} +.icon-external-link-sign:before{content:"\f14c";} +.icon-share-sign:before{content:"\f14d";} +.icon-compass:before{content:"\f14e";} +.icon-collapse:before{content:"\f150";} +.icon-collapse-top:before{content:"\f151";} +.icon-expand:before{content:"\f152";} +.icon-euro:before,.icon-eur:before{content:"\f153";} +.icon-gbp:before{content:"\f154";} +.icon-dollar:before,.icon-usd:before{content:"\f155";} +.icon-rupee:before,.icon-inr:before{content:"\f156";} +.icon-yen:before,.icon-jpy:before{content:"\f157";} +.icon-renminbi:before,.icon-cny:before{content:"\f158";} +.icon-won:before,.icon-krw:before{content:"\f159";} +.icon-bitcoin:before,.icon-btc:before{content:"\f15a";} +.icon-file:before{content:"\f15b";} +.icon-file-text:before{content:"\f15c";} +.icon-sort-by-alphabet:before{content:"\f15d";} +.icon-sort-by-alphabet-alt:before{content:"\f15e";} +.icon-sort-by-attributes:before{content:"\f160";} +.icon-sort-by-attributes-alt:before{content:"\f161";} +.icon-sort-by-order:before{content:"\f162";} +.icon-sort-by-order-alt:before{content:"\f163";} +.icon-thumbs-up:before{content:"\f164";} +.icon-thumbs-down:before{content:"\f165";} +.icon-youtube-sign:before{content:"\f166";} +.icon-youtube:before{content:"\f167";} +.icon-xing:before{content:"\f168";} +.icon-xing-sign:before{content:"\f169";} +.icon-youtube-play:before{content:"\f16a";} +.icon-dropbox:before{content:"\f16b";} +.icon-stackexchange:before{content:"\f16c";} +.icon-instagram:before{content:"\f16d";} +.icon-flickr:before{content:"\f16e";} +.icon-adn:before{content:"\f170";} +.icon-bitbucket:before{content:"\f171";} +.icon-bitbucket-sign:before{content:"\f172";} +.icon-tumblr:before{content:"\f173";} +.icon-tumblr-sign:before{content:"\f174";} +.icon-long-arrow-down:before{content:"\f175";} +.icon-long-arrow-up:before{content:"\f176";} +.icon-long-arrow-left:before{content:"\f177";} +.icon-long-arrow-right:before{content:"\f178";} +.icon-apple:before{content:"\f179";} +.icon-windows:before{content:"\f17a";} +.icon-android:before{content:"\f17b";} +.icon-linux:before{content:"\f17c";} +.icon-dribbble:before{content:"\f17d";} +.icon-skype:before{content:"\f17e";} +.icon-foursquare:before{content:"\f180";} +.icon-trello:before{content:"\f181";} +.icon-female:before{content:"\f182";} +.icon-male:before{content:"\f183";} +.icon-gittip:before{content:"\f184";} +.icon-sun:before{content:"\f185";} +.icon-moon:before{content:"\f186";} +.icon-archive:before{content:"\f187";} +.icon-bug:before{content:"\f188";} +.icon-vk:before{content:"\f189";} +.icon-weibo:before{content:"\f18a";} +.icon-renren:before{content:"\f18b";} diff --git a/content/css/usergrid-site.css b/content/css/usergrid-site.css new file mode 100644 index 0000000000..e4bc3f2b26 --- /dev/null +++ b/content/css/usergrid-site.css @@ -0,0 +1,1553 @@ +@import url("http://fonts.googleapis.com/css?family=Open+Sans:400,300,600,800,700,400italic,600italic,700italic,800italic,300italic"); +/* @import url("http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,700"); */ +/* Key scaffolding +-------------------------------------------------- */ +body { + position: relative; /* For scrollyspy */ + padding-top: 50px; /* Account for fixed navbar */ + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif !important; + font-size:14px; + background-color: #FAFBFC; + /*font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; */ +} +h1, h2, h3, h4, .h1, .h2, .h3, .h4 { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif !important; + font-weight: 300; +} +a:hover {text-decoration: none;} +h2>a, h3>a, h2>a:hover, h3>a:hover { color: rgb(51,51,51); } +h2:hover>a:after { + content: "\F0C1"; + font-family: 'FontAwesome'; + /*position:absolute;*/ + padding-left: 12px; + vertical-align: 15%; + font-size: 20px; +} +h3:hover>a:after { + content: "\F0C1"; + font-family: 'FontAwesome'; + /*position:absolute;*/ + padding-left: 8px; + vertical-align: 15%; + font-size: 15px; +} +h5, h6, .h5, .h6 { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif !important; +} +.bf-sidebar .nav-list code{ + margin-left: -3px; +} +.done { + opacity: 0.6; +} +.nav-list > li { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 400 !important; + opacity: 0.8; + margin-bottom: 3px; +} +header .navbar-nav { + font-size: 120%; +} +.nav-list > li > ul { + padding-left: 0; +} +.nav-list > li ul ul { + padding-left: 19px; +} +.nav-list > li ul > li { + list-style-type: none !important; +} +.nav-list > li ul > li:before { + content:"\221F"; + font-weight: 200; + opacity: 0.5; + line-height: 50%; + vertical-align: 60%; + padding-left: 3px; +} +.nav-list > li ul > li > a { + padding: 0 0 0 3px; + margin-bottom: 0px; +} +.nav-list > li > a { + padding: 0; +} +.nav-list > li > a.icns-apple:before { + text-align: right; + content: "\F179"; + font-family: 'FontAwesome'; + font-size: 110%; + margin-left: -18px; + padding-right: 8px; + line-height: 0; +} +.nav-list > li > a.icns-android:before { + text-align: right; + content: "\F17B"; + font-family: 'FontAwesome'; + font-size: 110%; + margin-left: -18px; + padding-right: 8px; + line-height: 0; +} +.nav-list > li > a.icns-html5:before { + text-align: right; + content: "\F13B"; + font-family: 'FontAwesome'; + font-size: 110%; + margin-left: -18px; + padding-right: 8px; + line-height: 0; +} +.nav-list > li > a.icns-windows:before { + text-align: right; + content: "\F17A"; + font-family: 'FontAwesome'; + margin-left: -19px; + padding-right: 7px; + line-height: 0; +} +li.nav-header { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600 !important; + opacity: 1.0; + padding-top: 0 !important; + padding-left: 0 !important; + font-size: 120%; + margin-top: 33px; +} +.twitter-timeline { + margin-top: 33px; +} +.bf-docs-container .nav-list li.nav-header { + padding: 0 !important; + border-bottom: solid 1px #ccc; + line-height: 0; + margin-top: 33px; + margin-bottom: 13px; +} +.bf-docs-container .nav-list li.nav-header span { + background-color: #FAFBFC; + padding-right: 8px; +} + +.bf-community h2, .bf-docs-container h2, .bf-docs-container h3 { + padding-top: 90px; + margin-top: -60px; +} + +.bf-docs-container .github-callout { + padding: 20px 0 40px 0; + font-style: italic; + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + opacity: 0.8; + font-size: 110%; +} +.navbar-nav > li a { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 300 !important; + opacity: 0.8; +} + +.navbar-nav > li > a.major { + font-weight: 400 !important; + opacity: 1.0; +} + +.navbar-collapse { + max-height: none; +} + +.bf-masthead-bg p { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: 200; + font-size: 120%; + line-height: 120%; +} +.bf-features p { + font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: 400; +} +.bf-features p a { + /*font-weight: 600;*/ + /*color: rgb(52,73,94);*/ +} +a.btn { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 500 !important; + font-style: normal; + letter-spacing: 110%; +} +h1 { + font-weight: 200; + letter-spacing: 110%; + font-size: 200%; +} +.page-header { + padding-top: 2px; +} +.page-header h1 { + padding-top:20px; + font-weight: 400; + font-size:350%; +} +.page-header small{ + float: right; + background-color: #fff; + padding-left: 10px; +} +.page-header small a { + color: #ddd; + font-style: italic; +} +.page-header small a:hover { + color: #2481A6; +} +h2 { + font-weight: 400; +} +h3 { + padding-top: 20px; + font-weight: 400 !important; +} +.bf-features h3 { + padding-top: 0; +} +#copyright { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 300 !important; + font-style: italic; +} +#copyright img { + border-radius: 4px; +} +#copyright p { + opacity: 0.8; +} +#copyright .credits { + color: #fff; + font-weight: 600; + opacity: 1 !important; + font-style: normal; +} +.table { + margin: 20px 0 0 0; + background-color: transparent; +} +.table thead>tr>th, .table tbody>tr>th, .table tfoot>tr>th, .table thead>tr>td, .table tbody>tr>td, .table tfoot>tr>td { + padding-left: 0; +} +.toc { + margin-bottom:40px; + /*background-color: #fff; + border-radius: 4px;*/ + /*padding: 20px;*/ +} +/*.toc > h4 { + padding-top: 0; + margin-top: 0; + font-size: 150%; + font-weight:400; +}*/ +.toc > ul { + margin-bottom: 0; + padding-left: 20px; +} +section > .container > h2 { + color: #2481A6 !important; +} +div.row > div.text-left > h2 { + margin-top: 40px; + margin-bottom: 10px; +} +.bf-docs-container h2 { + font-size: 250%; +} +/* font-face +-------------------------------------------------- */ +@font-face { + font-family: 'icomoon'; + src:url('../fonts/icomoon.eot'); + src:url('../fonts/icomoon.eot?#iefix') format('embedded-opentype'), + url('../fonts/icomoon.woff') format('woff'), + url('../fonts/icomoon.ttf') format('truetype'), + url('../fonts/icomoon.svg#icomoon') format('svg'); + font-weight: normal; + font-style: normal; +} +[data-icon]:before { + font-family: 'icomoon'; + content: attr(data-icon); + speak: none; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-equalizer, .icon-phone-portrait, .icon-rocket, .icon-github, .icon-twitter, .icon-thumbf-up, .icon-earth, .icon-bug, .icon-wiki, .icon-releases,.icon-window { + font-family: 'icomoon'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-equalizer:before { + content: "\e000"; +} +.icon-phone-portrait:before { + content: "\e002"; +} +.icon-rocket:before { + content: "\e003"; +} +.icon-github:before { + content: "\e001"; +} +.icon-twitter:before { + content: "\e004"; +} +.icon-thumbf-up:before { + content: "\e005"; +} +.icon-earth:before { + content: "\e006"; +} +.icon-bug:before { + content: "\e007"; +} +.icon-window:before { + content: "\e008"; +} +.icon-wiki:before { + content: "\e009"; +} +.icon-releases:before { + content: "\e010"; +} +/* Custom docs button */ +.btn-bf { + color: #563d7c; + background-color: #fff; + border-color: #e5e5e5; +} +.btn-bf:hover, +.btn-bf:focus, +.btn-bf:active { + color: #fff; + background-color: #563d7c; + border-color: #563d7c; +} +/* Navs and headers +-------------------------------------------------- */ +header.navbar .container { + padding-right: 0; +} +footer > .container { + padding-right: 0; + padding-left: 0; +} +header.navbar.secondary { + box-shadow: 0px 1px 2px rgb(36,129,166); +} +.navbar-inverse { + background-color: rgb(36,129,166); +} +nav.navbar-collapse { + border-color: rgb(52, 73, 94) !important; + border-width: 1px; + box-shadow: none; + padding-left: 15px; +} +.bf-docs-nav { + border-bottom: 0px; + padding-left: 20px; + padding-right: 20px; +} +.navbar-nav { + margin: 0; +} + +.navbar-brand { + padding-left: 0; +} +.bf-docs-nav .navbar-nav > li > a { + margin: 10px 0 0 10px; + padding: 5px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + color: #fff; +} +.bf-docs-nav .navbar-nav > li > a:hover { + color: #fff; + background-color: #34495e; +} +.bf-docs-nav .navbar-nav > .active > a, +.bf-docs-nav .navbar-nav > .active > a:hover { + color: #fff; + background-color: #34495e !important; +} +li.divider { + margin-left: 0 !important; +} + +/* Homepage masthead +-------------------------------------------------- */ +.bf-masthead { + position: relative; + text-align: left; + /*background: #cbcbcd url(../img/rende.png) no-repeat 50% 100px;*/ +} +.bf-masthead .bf-masthead-bg { + /*margin-top: 10px;*/ + padding: 30px 15px; + color:#fff; + background-color: rgb(36,129,166); +} +/*.bf-masthead .logo { + height: 203px; +}*/ +.bf-masthead .logo-title { + width: 600px; + padding: 20px 0 0 0; + margin-left: 0; +} +.bf-masthead .text-container { + margin-left: auto; + margin-right: auto; + text-align: left; +} +.bf-masthead .tagline { + font-style:normal; + font-weight:200; + font-size: 300%; + margin-bottom: 0; + margin-top: 30px; + padding-bottom: 30px; + color: white; + line-height: 90%; +} +.bf-masthead .tagline em { + font-style: italic; +} +.bf-masthead .description { + font-style: normal; + font-size: 150%; + margin-bottom: 45px; + /*line-height: 100%;*/ +} +.bf-masthead .btn-wrapper { + text-align: center; + margin-bottom: 20px; + clear:both; +} +.bf-masthead .btn-wrapper { + text-align: left; + width: 100%; + margin-right: 20px; +} +.bf-masthead .social-btn { + float: left; + margin: 0 20px 10px 0; +} +.bf-masthead .or { + margin-left: 0px; + font-style: normal; + font-weight: 200; + opacity: 0.8; +} + +.bf-masthead a { + line-height: 30px; + color: #FAFBFC; + font-style: normal; + font-weight: 400; +} +.bf-masthead h1 { + font-size: 30px; + line-height: 1.4; + color: #fff; +} +.bf-masthead .bf-masthead-links a, +.bf-masthead .bf-masthead-links a:hover { + color: #fff; +} +.bf-masthead-info { + padding: 80px 20px; + font-size: 28px; + text-align: center; + background-color: #fc5d7b; + color: rgba(0, 0, 0, .3) +} +.bf-masthead-info .icon-angle-down { + font-size: 40px; +} + +/* Download button */ +.bf-masthead .btn-outline { + margin-top: 20px; + margin-bottom: 20px; + border: 1px solid #fff; + padding: 18px 24px; + font-size: 21px; + color: #fff; +} +.bf-masthead .btn-outline:hover { + background-color: #fff; + color: #42a8d2; +} + +.bf-masthead-links { + margin-top: 20px; + margin-bottom: 20px; + padding-left: 0; + list-style: none; + text-align: center; +} +.bf-masthead-links li { + margin-bottom: 15px; + color: #fff; +} +.bf-masthead-links a { + color: #c8c7c6; +} + +/* Homepage features +-------------------------------------------------- */ +section > .container > h2 { + text-align: left; + margin-bottom: 16px; + padding-bottom: 6px; + font-size: 28px; + color:#666666; + /* border-bottom: 1px solid #e5e5e5; */ +} +.bf-features { + color: #292929; + text-align: center; + padding: 20px 0; +} +.bf-features h2 ~ p { + margin-bottom: 40px; + font-size: 16px; +} +.bf-features .bf-icon-wrap { + margin: 0 auto 10px; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + background-color: rgb(52,73,94); + width: 90px; + height: 90px; + line-height: 90px; + font-size: 50px; + color: #FAFBFC; +} +.bf-features h3 { + margin: 0 0 10px; + color: rgb(52,73,94); + font-weight: 400 !important; +} +.bf-features h3 ~ p { + color: #656565; +} +/* +.bf-features2 { + color: #292929; + text-align: center; +} +.bf-features2 { + padding: 40px 0; +} +.bf-features2 h2 { + text-align: left; + margin-bottom: 16px; + padding-bottom: 6px; + font-size: 28px; + color:#666666; + border-bottom: 1px solid #e5e5e5; +} +.bf-features2 h2 ~ p { + margin-bottom: 40px; + font-size: 16px; +} +.bf-features2 .bf-icon-wrap { + margin: 0 auto 20px; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + background-color: #e5e9ed; + width: 80px; + height: 80px; + line-height: 80px; + font-size: 40px; + color: #a5b6c7; +} +.bf-features2 h3 { + margin: 0 0 10px; + color: #696969; +} +.bf-features2 h3 ~ p { + color: #656565; +} */ +.bf-features-inverse { + padding: 140px 0; + font-size: 16px; + color: #fff; + text-align: center; + background-color: #34495e; +} +.bf-features-inverse h2 { + margin-bottom: 20px; + font-size: 40px; +} +.bf-features-inverse h2 ~ p { + margin-bottom: 40px; + font-size: 16px; +} +.bf-features-inverse .bf-icon-wrap { + margin: 0 auto 20px; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + background-color: #fff; + width: 80px; + height: 80px; + line-height: 80px; + font-size: 40px; + color: #3dc0f1; +} +.bf-features-inverse h3 ~ p { + font-size: 14px; +} +.bf-features-inverse a, +.bf-features-inverse a:hover { + color: #fff; + text-decoration: underline; +} +.bf-news ul { + margin-bottom: 20px; +} + +.bf-questions .container { + border-top: 1px solid rgb(52,73,94); + border-bottom: 1px solid rgb(52,73,94); + padding: 60px 0; + margin-top: 0px; +} + +.bf-questions div { + line-height: 30px; +} + +.bf-community .container, .bf-tagline .container { + padding-left: 0; + padding-right: 0; +} + +.bf-community h3 { + font-weight: 600; + margin-top: 0; +} + +.bf-community .row a p { + color: rgb(51,51,51); +} + +/*.bf-community h2 { + padding-bottom: 10px; + border-bottom: 1px solid rgb(51,51,51); +}*/ + +.bf-community h2 { + /*padding: 0 !important;*/ + border-bottom: solid 1px #ccc; + line-height: 0; + /*margin-top: 33px;*/ + margin-bottom: 13px; +} +.bf-releases h2 { + /*padding: 0 !important;*/ + border-bottom: solid 1px #ccc; + line-height: 0; + /*margin-top: 33px;*/ + margin-bottom: 13px; +} + +.bf-community h2 span { + background-color: #FAFBFC; + padding-right: 10px; +} + + +.bf-releases h2 span { + background-color: #FAFBFC; + padding-right: 10px; +} + +.bf-releases p { + padding: 10px 0 5px 0; +} + +.bf-community { + margin-top: 80px; +} + +.bf-releases { + margin-top: 10px; +} + +#map-canvas { + border-bottom: 1px solid rgb(52, 73, 94); +} + +.bf-community img { + border-radius: 4px; + border: solid 1px rgb(52, 73, 94); + margin-top: 20px; + margin-bottom: 10px; + width: 100%; + box-shadow: rgb(52, 73, 94) 2px 2px 4px; +} + +.bf-releases img { + border-radius: 4px; + border: solid 1px rgb(52, 73, 94); + margin-top: 20px; + margin-bottom: 10px; + width: 100%; + box-shadow: rgb(52, 73, 94) 2px 2px 4px; +} + + +h2.icns-calendar:before{ + text-align: right; + content: "\F073"; + font-family: 'FontAwesome'; + font-size: 100%; + margin-left: -40px; + padding-right: 10px; + line-height: 0; +} +h2.icns-chat:before{ + text-align: right; + content: "\F0FC"; + font-family: 'FontAwesome'; + font-size: 100%; + margin-left: -40px; + padding-right: 10px; + line-height: 0; +} + +h2.icns-envelope:before{ + text-align: right; + content: "\F0E0"; + font-family: 'FontAwesome'; + font-size: 100%; + margin-left: -40px; + padding-right: 10px; + line-height: 0; +} +h2.icns-briefcase:before{ + text-align: right; + content: "\F0B1"; + font-family: 'FontAwesome'; + font-size: 100%; + margin-left: -42px; + padding-right: 10px; + line-height: 0; +} +h2.icns-group:before{ + text-align: right; + content: "\F005"; + font-family: 'FontAwesome'; + font-size: 100%; + margin-left: -37px; + padding-right: 8px; + line-height: 0; +} +h2.icns-tools:before{ + text-align: right; + content: "\F006"; + font-family: 'FontAwesome'; + font-size: 100%; + margin-left: -37px; + padding-right: 8px; + line-height: 0; +} +/* Docs pages and sections +-------------------------------------------------- */ + +/* Page headers */ +.bf-header { + padding: 5px 20px 10px; + font-size: 16px; + color: #5a5a5a; + text-align: center; + border-bottom: 1px solid #e5e5e5; +} +.bf-header p { + font-weight: 300; + line-height: 1.5; +} +.bf-header .container { + position: relative; +} + +.bf-docs-container { + margin-top: 60px; +} + +.bf-docs-container .col-md-3{ + padding-left: 0; +} + + +.bf-docs-container .col-md-9.main-article { + background-color: #fff; + border-radius: 4px; + border: 1px solid #ccc; + padding-bottom: 15px; + min-height: 820px; +} + +.bf-docs-section + .bf-docs-section { + padding-top: 20px; +} + +.bf-docs-container .nav-list { + padding-top: 20px; +} + +/* Bootstrap code examples +-------------------------------------------------- */ + +/* Base class */ +.bf-example { + position: relative; + margin: 20px 0 40px; +} +.bf-example > .btn-toolbar + .btn-toolbar { + margin-top: 10px; +} + +.bf-example .row { + margin-bottom: 20px; +} + +/* Tweak display of the examples */ +.bf-example + .highlight { + margin: 0 -15px; + border-radius: 0; + border-width: 0 0 1px; +} + +/* Tweak content of examples for optimum awesome */ +.bf-example > p:last-child, +.bf-example > ul:last-child, +.bf-example > ol:last-child, +.bf-example > blockquote:last-child, +.bf-example > input:last-child, +.bf-example > select:last-child, +.bf-example > textarea:last-child, +.bf-example > .table:last-child, +.bf-example > .navbar:last-child +.bf-example > .jumbotron:last-child, +.bf-example > .alert:last-child, +.bf-example > .panel:last-child, +.bf-example > .list-group:last-child, +.bf-example > .well:last-child { + margin-bottom: 0; +} +.bf-example > p > .close { + float: none; +} +.bf-example-title { + border-left: 3px solid #08d; + padding-left: 10px; + line-height: 24px; + margin: 20px 0; + font-size: 16px; +} +.bf-example-align .btn { + margin-top: 4px; +} +.bf-example-align .btn-xs { + margin-top: 16px; +} +.bf-example-align .btn-sm { + margin-top: 8px; +} +.bf-example-align .btn-lg { + margin-top: -7px; +} + +/* Navbar examples */ +.bf-example .navbar:last-child { + margin-bottom: 0; +} +.bf-navbar-top-example, +.bf-navbar-bottom-example { + z-index: 1; + padding: 0; + min-height: 110px; + overflow: hidden; /* cut the drop shadows off */ +} +.bf-navbar-top-example .navbar-fixed-top, +.bf-navbar-bottom-example .navbar-fixed-bottom { + position: relative; + margin-left: 0; + margin-right: 0; +} +.bf-navbar-top-example .navbar-fixed-top { + top: -1px; +} +.bf-navbar-bottom-example .navbar-fixed-bottom { + bottom: -1px; +} +.bf-navbar-top-example { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} +.bf-navbar-top-example:after { + top: auto; + bottom: 15px; + -webkit-border-radius: 0 4px 0 4px; + -moz-border-radius: 0 4px 0 4px; + border-radius: 0 4px 0 4px; +} +.bf-navbar-bottom-example { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} +.bf-navbar-bottom-example .navbar { + margin-bottom: 0; +} +.bf-navbar-top-example.bf-example:after { + bottom: -1px; + border-radius: 0 4px; +} + +/* Example modals */ +.bf-example-modal { + background-color: #f5f5f5; +} +.bf-example-modal .modal { + position: relative; + top: auto; + right: auto; + left: auto; + bottom: auto; + z-index: 1; + display: block; +} +.bf-example-modal .modal-dialog { + left: auto; + margin-left: auto; + margin-right: auto; +} + +/* Example dropdowns */ +.bf-example > .dropdown > .dropdown-menu, +.bf-example-submenu > .pull-left > .dropup > .dropdown-menu, +.bf-example-submenu > .pull-left > .dropdown > .dropdown-menu { + position: static; + display: block; + margin-bottom: 5px; +} +.bf-example-submenu { + min-height: 230px; +} +.bf-example-submenu > .pull-left + .pull-left { + margin-left: 20px; +} + +/* Tooltips */ +.bf-example-tooltips { + text-align: center; +} + +/* Popovers */ +.bf-example-popover { + padding-bottom: 24px; +} +.bf-example-popover .popover { + position: relative; + display: block; + float: left; + width: 260px; + margin: 20px; +} + +/* Example templates +-------------------------------------------------- */ + +.bf-examples h4 { + margin-bottom: 5px; +} +.bf-examples p { + margin-bottom: 20px; +} + +/* Responsive docs +-------------------------------------------------- */ + +/* Responsive (scrollable) doc tables */ +@media (max-width: 768px) { + .bf-table-scrollable { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + overflow-x: scroll; + border: 1px solid #ddd; + } + .bf-table-scrollable .table { + margin-bottom: 0; + border: 0; + } + .bf-table-scrollable .table th, + .bf-table-scrollable .table td { + white-space: nowrap; + } + .bf-table-scrollable .table th:first-child, + .bf-table-scrollable .table td:first-child { + border-left: 0; + } + .bf-table-scrollable .table th:last-child, + .bf-table-scrollable .table td:last-child { + border-right: 0; + } + .bf-table-scrollable .table tr:last-child th, + .bf-table-scrollable .table tr:last-child td { + border-bottom: 0; + } +} + +/* Footer +-------------------------------------------------- */ + +.bf-footer { + margin-top: 40px; + padding: 30px 5px; + /*text-align: left;*/ + background:#34495e; + color:#f0f0f0; +} + +.bf-footer a { + color:#f0f0f0 !important; +} +.bf-footer.bf-footer-margin { + margin-top: 100px; + margin-bottom: 20px; +} + +.bf-footer .bf-icon-wrap { + font-size: 40px; + color: #a5b6c7; + display: inline; + margin: 10px; +} + +#footer-icons { + float: right; + display: inline; + line-height: 20px; + margin: 40px 10px 20px 10px; +} + +#copyright { + float: left; + display: inline; + line-height: 20px; + margin: 20px 10px 20px 10px; +} + +/* Social proof buttons from GitHub & Twitter */ +.bf-social { + margin-bottom: 20px; +} +.bf-social-buttons { + display: inline-block; + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.bf-social-buttons li { + display: inline-block; + line-height: 1; +} +.bf-social-buttons li + li { + margin-left: 15px; +} +.bf-social-buttons .twitter-follow-button { + width: 225px !important; +} +.bf-social-buttons .twitter-share-button { + width: 98px !important; +} +/* Style the GitHub buttons via CSS instead of inline attributes */ +.github-btn { + border: 0; + overflow: hidden; +} + +.highlight { + padding: 9px 14px; + margin-bottom: 40px; + border: 1px solid #e1e1e8; + border-radius: 4px; +} +.highlight pre { + padding: 0; + margin-top: 0; + margin-bottom: 0; + background-color: rgb(248, 248, 255); + border: 0; + white-space: nowrap; +} +.highlight pre code { + font-size: inherit; + font-family: Consolas, 'Liberation Mono', Courier, monospace; + color: #333; /* Effectively the base text color */ +} +.highlight pre .lineno { + display: inline-block; + width: 22px; + padding-right: 5px; + margin-right: 10px; + text-align: right; + color: #bebec5; +} + +.c { color: #999988; font-style: italic } /* Comment */ +.err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.k { color: #000000; font-weight: bold } /* Keyword */ +.o { color: #000000; font-weight: bold } /* Operator */ +.cm { color: #999988; font-style: italic } /* Comment.Multiline */ +.cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */ +.c1 { color: #999988; font-style: italic } /* Comment.Single */ +.cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ +.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.ge { color: #000000; font-style: italic } /* Generic.Emph */ +.gr { color: #aa0000 } /* Generic.Error */ +.gh { color: #999999 } /* Generic.Heading */ +.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.go { color: #888888 } /* Generic.Output */ +.gp { color: #555555 } /* Generic.Prompt */ +.gs { font-weight: bold } /* Generic.Strong */ +.gu { color: #aaaaaa } /* Generic.Subheading */ +.gt { color: #aa0000 } /* Generic.Traceback */ +.kc { color: #000000; font-weight: bold } /* Keyword.Constant */ +.kd { color: #000000; font-weight: bold } /* Keyword.Declaration */ +.kn { color: #000000; font-weight: bold } /* Keyword.Namespace */ +.kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */ +.kr { color: #000000; font-weight: bold } /* Keyword.Reserved */ +.kt { color: #445588; font-weight: bold } /* Keyword.Type */ +.m { color: #009999 } /* Literal.Number */ +.s { color: #d01040 } /* Literal.String */ +.na { color: #008080 } /* Name.Attribute */ +.nb { color: #0086B3 } /* Name.Builtin */ +.nc { color: #445588; font-weight: bold } /* Name.Class */ +.no { color: #008080 } /* Name.Constant */ +.nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */ +.ni { color: #800080 } /* Name.Entity */ +.ne { color: #990000; font-weight: bold } /* Name.Exception */ +.nf { color: #990000; font-weight: bold } /* Name.Function */ +.nl { color: #990000; font-weight: bold } /* Name.Label */ +.nn { color: #555555 } /* Name.Namespace */ +.nt { color: #000080 } /* Name.Tag */ +.nv { color: #008080 } /* Name.Variable */ +.ow { color: #000000; font-weight: bold } /* Operator.Word */ +.w { color: #bbbbbb } /* Text.Whitespace */ +.mf { color: #009999 } /* Literal.Number.Float */ +.mh { color: #009999 } /* Literal.Number.Hex */ +.mi { color: #009999 } /* Literal.Number.Integer */ +.mo { color: #009999 } /* Literal.Number.Oct */ +.sb { color: #d01040 } /* Literal.String.Backtick */ +.sc { color: #d01040 } /* Literal.String.Char */ +.sd { color: #d01040 } /* Literal.String.Doc */ +.s2 { color: #d01040 } /* Literal.String.Double */ +.se { color: #d01040 } /* Literal.String.Escape */ +.sh { color: #d01040 } /* Literal.String.Heredoc */ +.si { color: #d01040 } /* Literal.String.Interpol */ +.sx { color: #d01040 } /* Literal.String.Other */ +.sr { color: #009926 } /* Literal.String.Regex */ +.s1 { color: #d01040 } /* Literal.String.Single */ +.ss { color: #990073 } /* Literal.String.Symbol */ +.bp { color: #999999 } /* Name.Builtin.Pseudo */ +.vc { color: #008080 } /* Name.Variable.Class */ +.vg { color: #008080 } /* Name.Variable.Global */ +.vi { color: #008080 } /* Name.Variable.Instance */ +.il { color: #009999 } /* Literal.Number.Integer.Long */ + +.css .o, +.css .o + .nt, +.css .nt + .nt { color: #999; } +/* Show code snippets when we have the space */ +@media screen and (min-width: 481px) { + .highlight { + display: block; + } +} + +.demoColorSwatches { + color: #FFF; +} +.demoColorSwatches h4 { + color: #292929; +} +.demoColorSwatches .colorPanel { + padding: 15px; +} +.demoColorSwatches .colorPanel:hover { + opacity: 0.85; + filter: alpha(opacity=85); +} + +/* Responsive variations +-------------------------------------------------- */ + +/* Hide code snippets on mobile devices */ +@media screen and (max-width: 480px) { + .highlight { + display: none; + } +} + + +.bf-docs-container { + margin-top: 40px; +} + +/* Navbars */ +.bf-example .navbar:last-child { + margin-bottom: 0; +} +.bf-navbar-top-example, +.bf-navbar-bottom-example { + z-index: 1; + padding: 0; + overflow: hidden; /* cut the drop shadows off */ + border: 1px solid #ddd ; +} +.bf-navbar-top-example .navbar-header, +.bf-navbar-bottom-example .navbar-header { + margin-left: 0; +} +.bf-navbar-top-example .navbar-fixed-top, +.bf-navbar-bottom-example .navbar-fixed-bottom { + position: relative; + margin-left: 0; + margin-right: 0; +} +.bf-navbar-top-example { + padding-bottom: 45px; +} +.bf-navbar-top-example:after { + top: auto; + bottom: 15px; +} +.bf-navbar-top-example .navbar-fixed-top { + top: -1px; +} +.bf-navbar-bottom-example { + padding-top: 65px; +} +.bf-navbar-bottom-example .navbar-fixed-bottom { + bottom: -1px; +} +.bf-navbar-bottom-example .navbar { + margin-bottom: 0; +} + +/* Phone and below */ +@media screen and (max-width: 768px) { + #home-logo { opacity: 1; height: 25px;} + span.icon-book:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Docs"; + } + span.icon-group:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Community"; + } + span.icon-github-sign:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Github"; + } + span.icon-trello:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Trello"; + } + span.icon-bug:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " JIRA"; + } + span.icon-stackexchange:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " StackOverflow"; + } + span.icon-chat:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " HipChat"; + } + span.icon-twitter:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Twitter"; + } + span.icon-wiki:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Wiki"; + } + span.icon-releases:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Releases"; + } + span.icon-comments:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Chat"; + } + span.icon-envelope:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Mailing Lists"; + } + div.cta { + line-height: 60px; + } + span.avoidwrap { display:inline-block; } + .navbar-nav > li > a { + opacity: 1.0; + } + .bf-masthead .tagline { + line-height: 90%; + } + + .bf-masthead .description { + margin-bottom: 30px; + } + .bf-masthead p { + clear:both; + line-height: 100%; + padding-top: 5px; + } + .bf-masthead .or { + margin-right: 0; + } + .bf-questions .container{ + padding: 30px 0; + } +} + +/* Phones and Tablets */ +/*@media screen and (min-width: 768px) and (max-width: 992px) { + + .bf-masthead .tagline { + padding-bottom: 20px; + } + +}*/ + +@media screen and (max-width: 992px) { + .bf-community.committers .col-md-3 p{ + margin-bottom: 40px; + } +} + +/* Tablets and below */ +@media screen and (max-width: 1200px) { + .row { + padding: 0 25px; + } + .bf-docs-container .nav-list { + padding-left: 30px; + } + .bf-docs-container .colb-md-3 .nav-list { + padding-top: 0; + } + .bf-community .container, .bf-tagline .container { + padding-left: 50px; + } + .bf-community.committers .col-md-3 h3{ + margin-top: 0px; + } + #map-canvas { height: 300px; margin-top: 5px;} +} +/* Tablets and up */ +@media screen and (min-width: 768px) { + header.secondary #home-logo { opacity: 1; } + #home-logo { opacity: 0; height: 30px;} + .bf-header { + font-size: 21px; + text-align: left; + } + .bf-header h1 { + font-size: 60px; + line-height: 1; + } + + .bf-masthead p { + float:left; + } + + .bf-masthead .or { + margin-right: 20px; + } + .bf-features .row { + padding: 20px 0; + } + .bf-example { + margin-left: 0; + margin-right: 0; + border-radius: 4px; + background-color: #fff; + border-width: 1px; + border-color: #ddd; + box-shadow: none; + } + .bf-example + .prettyprint, + .bf-example + .highlight { + margin-top: -16px; + margin-left: 0; + margin-right: 0; + border-width: 1px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + } + + /* Show the docs nav */ + .bf-sidebar { + display: block; + } + .bf-sidebar > .nav > li > a { + display: inline-block; + } + + .bf-navbar-top-example .navbar-fixed-top, + .bf-navbar-bottom-example .navbar-fixed-bottom { + position: absolute; + } + .bs-navbar-top-example { + border-radius: 0 0 4px 4px; + } + .bs-navbar-bottom-example { + border-radius: 4px 4px 0 0; + } +} + +/* Tablets */ +@media screen and (min-width: 768px) and (max-width: 1200px) { + span.icns { + font-size: 140%; + } +} + +/* Tablets/desktops and up */ +@media screen and (min-width: 1200px) { + span.icon-book:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Docs"; + } + span.icon-group:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Community"; + } + span.icon-github-sign:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Github"; + } + span.icon-trello:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Trello"; + } + span.icon-bug:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " JIRA"; + } + span.icon-stackexchange:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " StackOverflow"; + } + span.icon-chat:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " HipChat"; + } + span.icon-twitter:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Twitter"; + } + span.icon-wiki:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Wiki"; + } + span.icon-releases:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Releases"; + } + span.icon-comments:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Chat"; + } + span.icon-envelope:after { + font-family: 'klavika-web', 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-weight: 600; + content: " Mailing Lists"; + } + .bf-header h1, + .bf-header p { + margin-right: 380px; + } + .bf-docs-container { + margin-top: 40px; + } + + .bf-masthead .tagline, .bf-masthead .description, .bf-masthead .btn-wrapper { + margin-left: 120px; + } + .bf-community.committers .col-md-3 h3{ + margin-top: 40px; + } + .bf-community.committers img { + width: 100%; + } + #map-canvas { height: 500px; margin-top: 10px;} + +} + +.navbar-toggle { + background-color: rgb(36,129,166); + margin: 12px 0 0 0; +} diff --git a/sdks/dotnet/packages/NSubstitute.1.6.0.0/README.txt b/content/docs/.gitkeep similarity index 100% rename from sdks/dotnet/packages/NSubstitute.1.6.0.0/README.txt rename to content/docs/.gitkeep diff --git a/content/docs/README.html b/content/docs/README.html new file mode 100644 index 0000000000..03856edfb5 --- /dev/null +++ b/content/docs/README.html @@ -0,0 +1,387 @@ + + + + + + + + + + + Apache Usergrid Documentation — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Apache Usergrid Documentation

+

Usergrid documentation is written in +Markdown (*.md) +and RST (.rst) formats and we use the Python based +Sphinx-Docs documentation system to +transform our Markdown and RST files to HTML format.

+
+

Prerequisites

+

Sphinx requires Python and pip. Once you have Python, you can install +sphinx and pip like so:

+
$ sudo easy_install sphinx
+$ sudo easy_install pip
+
+
+
+
+

How to build the Usergrid documentation using Sphinx

+

Sphinx runs via a Makefile in this, the docs directory. So, cd to this +directory and make html:

+
cd $usergrid/docs
+make clean html
+
+
+
+
+

How to update the Usergrid docs

+

Find the Markdown (.md) or reST (.rst) files that you need to change, +edit them and then run make clean html to generate the HTML into the +target/html directory, where you can preview your changes.

+
+

Note the difference between RST and Markdown files

+

Note that Sphinx’s native format is +reStructuredText (RST) +and not Markdown. This causes some issues. For example, using Sphinx +directives in Markdown files sometimes works and sometimes does not. RST +is a different format than Markdown and it has a different set of +directives, some very useful for organizing a large set of documentation +files.

+
+
+

Updating the Table of Contents

+

The Table of Contents for the documentation is in index.rst, which ties +everything together with a series of RST toctree directives. All +other files should be written in Markdown, unless they need some special +RST directives that will not work in Markdown.

+
+
+

Dealing with other tables

+

A note about tables. Markdown and reST do not have very good table +support. Simple tables are easy to do and you can find examples (e.g. +connecting-entities.md) but for tables with multiple lines in each cell, +you’ll probably want to use a raw HTML table, and there are plenty of +examples of that around too.

+
+
+
+

How to publish the Usergrid docs to Usergrid website

+

First you generate the HTML for the docs from the Markdown and reST +sources like so:

+
cd $usergrid/docs
+make clean html
+
+
+

To update the Usergrid website you must copy the udpated docs files from +target/html directory to the website directory at the root of the +Usergrid project, i.e. ${usergrid-project-dir}/website/docs.

+

You can do this by running the script update-website.sh.

+

Once you’ve done that then you should follow the instructions in the +website/README.md file, which explains how to update the website.

+
+
+

Updating the REST API reference

+

The REST API documentation in rest-endpoints/api-docs.md is +generated from a Swagger file in the directory src/main/resources, +so DO NOT edit that file directly.

+

If you need to update the REST API docs, you should edit the +usergrid-swagger.yaml file and then re-generate the file.

+

If you need to change the formatting of the REST API docs, then you will +need to edit the Mustache templates in src/main/resource and you may +need to edit the Groovy script that does the generation: +src/main/groovy/usergrid.ApiDocGenerator.

+

You will need: * Groovy 2.x * +Mustache.java

+

NOTE: Mustache.hava is not in Maven Central so unfortunately, you +will have to Git Clone Mustache.java before you can run the generation +script.

+

This is the command to run the generation:

+
groovy src/main/groovy/usergrid/ApiDocGenerator.groovy
+
+
+

The script will update the file rest-endpoints/api-docs.md and when +you are happy with your update you should commit and push that file with +Git.

+
+
+ + +
+
+
+ + +
+ +
+

+ © Copyright 2013-2015, Apache Usergrid. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/_images/asapp.png b/content/docs/_images/asapp.png new file mode 100644 index 0000000000..6a65f69098 Binary files /dev/null and b/content/docs/_images/asapp.png differ diff --git a/content/docs/_images/asemu.png b/content/docs/_images/asemu.png new file mode 100644 index 0000000000..09626df2ff Binary files /dev/null and b/content/docs/_images/asemu.png differ diff --git a/content/docs/_images/assettings.png b/content/docs/_images/assettings.png new file mode 100644 index 0000000000..7812a2e904 Binary files /dev/null and b/content/docs/_images/assettings.png differ diff --git a/content/docs/_images/cassandra.png b/content/docs/_images/cassandra.png new file mode 100644 index 0000000000..ac72781a3c Binary files /dev/null and b/content/docs/_images/cassandra.png differ diff --git a/content/docs/_images/gcmsetting.png b/content/docs/_images/gcmsetting.png new file mode 100644 index 0000000000..f238504a8d Binary files /dev/null and b/content/docs/_images/gcmsetting.png differ diff --git a/content/docs/_images/googleproj0.png b/content/docs/_images/googleproj0.png new file mode 100644 index 0000000000..86378b81a2 Binary files /dev/null and b/content/docs/_images/googleproj0.png differ diff --git a/content/docs/_images/iOS10seeusermsg.jpg b/content/docs/_images/iOS10seeusermsg.jpg new file mode 100644 index 0000000000..dfaee3197a Binary files /dev/null and b/content/docs/_images/iOS10seeusermsg.jpg differ diff --git a/content/docs/_images/iOS1chooseapp.jpg b/content/docs/_images/iOS1chooseapp.jpg new file mode 100644 index 0000000000..e81153f96f Binary files /dev/null and b/content/docs/_images/iOS1chooseapp.jpg differ diff --git a/content/docs/_images/iOS2register.jpg b/content/docs/_images/iOS2register.jpg new file mode 100644 index 0000000000..7666320ef5 Binary files /dev/null and b/content/docs/_images/iOS2register.jpg differ diff --git a/content/docs/_images/iOS5emptyfeed.jpg b/content/docs/_images/iOS5emptyfeed.jpg new file mode 100644 index 0000000000..6b03c67854 Binary files /dev/null and b/content/docs/_images/iOS5emptyfeed.jpg differ diff --git a/content/docs/_images/iOS6newmsg.jpg b/content/docs/_images/iOS6newmsg.jpg new file mode 100644 index 0000000000..0fe6164fe2 Binary files /dev/null and b/content/docs/_images/iOS6newmsg.jpg differ diff --git a/content/docs/_images/iOS7feed1msg.jpg b/content/docs/_images/iOS7feed1msg.jpg new file mode 100644 index 0000000000..f64d3783bb Binary files /dev/null and b/content/docs/_images/iOS7feed1msg.jpg differ diff --git a/content/docs/_images/ios-cert.png b/content/docs/_images/ios-cert.png new file mode 100644 index 0000000000..9582ea7100 Binary files /dev/null and b/content/docs/_images/ios-cert.png differ diff --git a/content/docs/_images/iospgapp.png b/content/docs/_images/iospgapp.png new file mode 100644 index 0000000000..a39391008a Binary files /dev/null and b/content/docs/_images/iospgapp.png differ diff --git a/content/docs/_images/iospgcert.png b/content/docs/_images/iospgcert.png new file mode 100644 index 0000000000..9582ea7100 Binary files /dev/null and b/content/docs/_images/iospgcert.png differ diff --git a/content/docs/_images/iospgsettings.png b/content/docs/_images/iospgsettings.png new file mode 100644 index 0000000000..9389bf1aad Binary files /dev/null and b/content/docs/_images/iospgsettings.png differ diff --git a/content/docs/_images/iospushauth.png b/content/docs/_images/iospushauth.png new file mode 100644 index 0000000000..42ab822552 Binary files /dev/null and b/content/docs/_images/iospushauth.png differ diff --git a/content/docs/_images/iospushfinal.png b/content/docs/_images/iospushfinal.png new file mode 100644 index 0000000000..440461c0d5 Binary files /dev/null and b/content/docs/_images/iospushfinal.png differ diff --git a/content/docs/_images/iospushsettings.png b/content/docs/_images/iospushsettings.png new file mode 100644 index 0000000000..44cd418318 Binary files /dev/null and b/content/docs/_images/iospushsettings.png differ diff --git a/content/docs/_images/iphonemessage.png b/content/docs/_images/iphonemessage.png new file mode 100644 index 0000000000..43f7ff9ce1 Binary files /dev/null and b/content/docs/_images/iphonemessage.png differ diff --git a/content/docs/_images/login.png b/content/docs/_images/login.png new file mode 100644 index 0000000000..565cf49e2d Binary files /dev/null and b/content/docs/_images/login.png differ diff --git a/content/docs/_images/pgaapp.png b/content/docs/_images/pgaapp.png new file mode 100644 index 0000000000..09e1cad0d8 Binary files /dev/null and b/content/docs/_images/pgaapp.png differ diff --git a/content/docs/_images/pgasettings.png b/content/docs/_images/pgasettings.png new file mode 100644 index 0000000000..aa6f2dfc3a Binary files /dev/null and b/content/docs/_images/pgasettings.png differ diff --git a/content/docs/_images/pgaspath.png b/content/docs/_images/pgaspath.png new file mode 100644 index 0000000000..09626df2ff Binary files /dev/null and b/content/docs/_images/pgaspath.png differ diff --git a/content/docs/_images/portal1.png b/content/docs/_images/portal1.png new file mode 100644 index 0000000000..0298f12391 Binary files /dev/null and b/content/docs/_images/portal1.png differ diff --git a/content/docs/_images/portal2.png b/content/docs/_images/portal2.png new file mode 100644 index 0000000000..71b787f101 Binary files /dev/null and b/content/docs/_images/portal2.png differ diff --git a/content/docs/_images/portal3.png b/content/docs/_images/portal3.png new file mode 100644 index 0000000000..89136a9a81 Binary files /dev/null and b/content/docs/_images/portal3.png differ diff --git a/content/docs/_images/portal4.png b/content/docs/_images/portal4.png new file mode 100644 index 0000000000..be644e5e36 Binary files /dev/null and b/content/docs/_images/portal4.png differ diff --git a/content/docs/_images/portal5.png b/content/docs/_images/portal5.png new file mode 100644 index 0000000000..f8781c5eaa Binary files /dev/null and b/content/docs/_images/portal5.png differ diff --git a/content/docs/_images/pushmiddleandroid0.png b/content/docs/_images/pushmiddleandroid0.png new file mode 100644 index 0000000000..1afd9542c3 Binary files /dev/null and b/content/docs/_images/pushmiddleandroid0.png differ diff --git a/content/docs/_images/pushmiddleios0.png b/content/docs/_images/pushmiddleios0.png new file mode 100644 index 0000000000..1ba14f142e Binary files /dev/null and b/content/docs/_images/pushmiddleios0.png differ diff --git a/content/docs/_images/pushsslcertificate.png b/content/docs/_images/pushsslcertificate.png new file mode 100644 index 0000000000..bab137dc5a Binary files /dev/null and b/content/docs/_images/pushsslcertificate.png differ diff --git a/content/docs/_images/rdbms.png b/content/docs/_images/rdbms.png new file mode 100644 index 0000000000..ce9f2a7b0e Binary files /dev/null and b/content/docs/_images/rdbms.png differ diff --git a/content/docs/_images/reviews.png b/content/docs/_images/reviews.png new file mode 100644 index 0000000000..3acb39de1f Binary files /dev/null and b/content/docs/_images/reviews.png differ diff --git a/content/docs/_images/reviews2.png b/content/docs/_images/reviews2.png new file mode 100644 index 0000000000..85872f2fad Binary files /dev/null and b/content/docs/_images/reviews2.png differ diff --git a/content/docs/_images/securitymodel0.png b/content/docs/_images/securitymodel0.png new file mode 100644 index 0000000000..9f3ee82815 Binary files /dev/null and b/content/docs/_images/securitymodel0.png differ diff --git a/content/docs/_images/sendnotification.png b/content/docs/_images/sendnotification.png new file mode 100644 index 0000000000..fb7d813945 Binary files /dev/null and b/content/docs/_images/sendnotification.png differ diff --git a/content/docs/_sources/README.txt b/content/docs/_sources/README.txt new file mode 100644 index 0000000000..2f7888cfc2 --- /dev/null +++ b/content/docs/_sources/README.txt @@ -0,0 +1,70 @@ +# Apache Usergrid Documentation + +Usergrid documentation is written in [Markdown](https://help.github.com/articles/markdown-basics/) (*.md) and RST (.rst) formats and we use the Python based [Sphinx-Docs](http://sphinx-doc.org/) documentation system to transform our Markdown and RST files to HTML format. + +## Prerequisites + +Sphinx requires Python and pip. Once you have Python, you can install sphinx and pip like so: + + $ sudo easy_install sphinx + $ sudo easy_install pip + +## How to build the Usergrid documentation using Sphinx + +Sphinx runs via a Makefile in this, the docs directory. So, cd to this directory and make html: + + cd $usergrid/docs + make clean html + +## How to update the Usergrid docs + +Find the Markdown (.md) or reST (.rst) files that you need to change, edit them and then run ``make clean html`` to generate the HTML into the ``target/html`` directory, where you can preview your changes. + +### Note the difference between RST and Markdown files + +Note that Sphinx's native format is [reStructuredText](http://docutils.sourceforge.net/rst.html) (RST) and not Markdown. This causes some issues. For example, using Sphinx directives in Markdown files sometimes works and sometimes does not. RST is a different format than Markdown and it has a different set of directives, some very useful for organizing a large set of documentation files. + +### Updating the Table of Contents + +The Table of Contents for the documentation is in index.rst, which ties everything together +with a series of RST __toctree__ directives. All other files should be written in Markdown, +unless they need some special RST directives that will not work in Markdown. + +### Dealing with other tables + +A note about tables. Markdown and reST do not have very good table support. Simple tables are easy to do and you can find examples (e.g. connecting-entities.md) but for tables with multiple lines in each cell, you'll probably want to use a raw HTML table, and there are plenty of examples of that around too. + +## How to publish the Usergrid docs to Usergrid website + +First you generate the HTML for the docs from the Markdown and reST sources like so: + + cd $usergrid/docs + make clean html + +To update the Usergrid website you must copy the udpated docs files from ``target/html`` directory to the website directory at the root of the Usergrid project, i.e. ``${usergrid-project-dir}/website/docs``. + +You can do this by running the script ``update-website.sh``. + +Once you've done that then you should follow the instructions in the website/README.md file, which explains how to update the website. + +## Updating the REST API reference + +The REST API documentation in ``rest-endpoints/api-docs.md`` is generated from a Swagger file in the +directory ``src/main/resources``, so DO NOT edit that file directly. + +If you need to update the REST API docs, you should edit the usergrid-swagger.yaml file and then + re-generate the file. + +If you need to change the formatting of the REST API docs, then you will need to edit the Mustache templates in ``src/main/resource`` and you may need to edit the Groovy script that does the generation: ``src/main/groovy/usergrid.ApiDocGenerator``. + +You will need: +* Groovy 2.x +* [Mustache.java](https://github.com/spullara/mustache.java) + +__NOTE__: Mustache.hava is not in Maven Central so unfortunately, you will have to Git Clone Mustache.java before you can run the generation script. + +This is the command to run the generation: + + groovy src/main/groovy/usergrid/ApiDocGenerator.groovy + +The script will update the file ``rest-endpoints/api-docs.md`` and when you are happy with your update you should commit and push that file with Git. diff --git a/content/docs/_sources/asset-and-files/assets.txt b/content/docs/_sources/asset-and-files/assets.txt new file mode 100644 index 0000000000..ea7291cd73 --- /dev/null +++ b/content/docs/_sources/asset-and-files/assets.txt @@ -0,0 +1,20 @@ +# Assets + +Asset entities are used primarily in Apache Usergrid to manage binary data +objects such as images, video, and audio content. However, an asset does +not have to be used for a binary object. For example, assets can be used +to model a file system. + + + Property Type Description + -------------- -------- --------------------------------------------------------------------------------- + uuid UUID Asset’s unique entity ID + type string "asset" + name string Asset name (mandatory) + created long [UNIX timestamp](http://en.wikipedia.org/wiki/Unix_time) of entity creation + modified long [UNIX timestamp](http://en.wikipedia.org/wiki/Unix_time) of entity modification + owner UUID UUID of the asset’s owner (mandatory) + path string Relative path to the asset (mandatory) + content-type string Content type of the asset (for example, “image/jpeg”) + +  diff --git a/content/docs/_sources/asset-and-files/file-storage-configuration.txt b/content/docs/_sources/asset-and-files/file-storage-configuration.txt new file mode 100644 index 0000000000..c56265aff5 --- /dev/null +++ b/content/docs/_sources/asset-and-files/file-storage-configuration.txt @@ -0,0 +1,39 @@ +# File storage configuration + +Usergrid can store your assets either on your hard drive or in the Amazon S3 cloud. + +Local storage configuration +--- + +By default assets are stored in the temporary folder /tmp/usergrid +This can be changed by editing this file /stack/rest/src/main/resources/usergrid-rest-context.xml and replacing {usergrid.temp.files} by the wanted destination +```xml + + + +``` + +AwS S3 configuration +--- + +To use your AWS S3 storage you need to change the binaryStore classpath and add several constructor arguments in /stack/rest/src/main/resources/usergrid-rest-context.xml + +Some examples : +```xml + + + + + + +``` +the regionName field is not mandatory, this code is also valid +```xml + + + + + +``` + +The filesize is limited to 50GB but you need to keep in mind that the file has to be stored on the hard drive before being sended to Amazon. diff --git a/content/docs/_sources/asset-and-files/folders.txt b/content/docs/_sources/asset-and-files/folders.txt new file mode 100644 index 0000000000..7c425be05e --- /dev/null +++ b/content/docs/_sources/asset-and-files/folders.txt @@ -0,0 +1,85 @@ +# Folders + +## Linking a folder to an asset +In order to access the asset for the image in the folder, you need to link the folder to the asset. You can do that by issuing a POST request in the following format: + + POST /{org-uuid}/{app-uuid}/folders/{folder-uuid}/assets/{assets_id} + +where ``{folder-uuid}`` is the UUID of the folder, and ``{assets-uuid}`` is the UUID of the assets entity. + +Here’s how you could link the folder and the asset you created for the my-image.jpg image: + + POST https://api.usergrid.com/my-org/my-app/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets/9501cda1-2d21-11e2-b4c6-02e81ac5a17b + +In the response, you should see the assets entity for the image added to the folder: + + { + "action": "post", + "application": "3400ba10-cd0c-11e1-bcf7-12313d1c4491", + "params": {}, + "path": "/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets", + "uri": "https://api.usergrid.com/my-org/my-app/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets", + "entities": [ + { + "uuid": "9501cda1-2d21-11e2-b4c6-02e81ac5a17b", + "type": "asset", + "name": "my-image.jpg", + "created": 1352763303163, + "modified": 1352763303163, + "metadata": { + "path": "/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets/9501cda1-2d21-11e2-b4c6-02e81ac5a17b" + }, + "owner": "5c0c1789-d503-11e1-b36a-12313b01d5c1", + "path": "/myassets/asset1" + } + ], + "timestamp": 1352830448045, + "duration": 54, + "organization": "my-org”, + "applicationName": "my-app" + } + +## Retrieve list of folder assets +You can also request a list of the linked contents of the folder like this: + + GET https://api.usergrid.com/my-org/my-app/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets + +The response should look something like this: + + { + "action": "get", + "application": "3400ba10-cd0c-11e1-bcf7-12313d1c4491", + "params": { + "_": [ + "1352830364891" + ] + }, + "path": "/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets", + "uri": "https://api.usergrid.com/my-org/my-app/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets", + "entities": [ + { + "uuid": "7bf47435-2ac8-11e2-b4c6-02e81ac5a17b", + "type": "asset", + "name": "my-image.jpg", + "created": 1352505133598, + "modified": 1352507245108, + "checksum": "8e0cd3866ee20746c99e9a9825f38ad8", + "content-length": 11853, + "content-type": "image/jpeg", + "etag": "\"8e0cd3866ee20746c99e9a9825f38ad8\"", + "metadata": { + "connecting": { + "assets": "/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets/7bf47435-2ac8-11e2-b4c6-02e81ac5a17b/connecting/assets" + }, + "connection": "assets", + "path": "/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets/7bf47435-2ac8-11e2-b4c6-02e81ac5a17b" + }, + "owner": "5c0c1789-d503-11e1-b36a-12313b01d5c1", + "path": "my-image" + } + ], + "timestamp": 1352830363797, + "duration": 57, + "organization": "my-org", + "applicationName": "my-app" + } diff --git a/stack/awscluster/src/main/dist/webapps/dummy.txt b/content/docs/_sources/asset-and-files/legacy-asset-support.txt similarity index 100% rename from stack/awscluster/src/main/dist/webapps/dummy.txt rename to content/docs/_sources/asset-and-files/legacy-asset-support.txt diff --git a/content/docs/_sources/asset-and-files/retrieving-assets.txt b/content/docs/_sources/asset-and-files/retrieving-assets.txt new file mode 100644 index 0000000000..9313ae8398 --- /dev/null +++ b/content/docs/_sources/asset-and-files/retrieving-assets.txt @@ -0,0 +1,27 @@ +# Retrieving assets + +## Retrieving asset data + +To retrieve the asset from an entity, send a ``GET`` request with the ``Accept`` header set to the content type of the asset. The content type can be retrieved from the ``file-metadata.content-type`` property of the entity the asset is attached to. + +### Request syntax + + curl -X GET -H 'Accept: ' 'https://api.usergrid.com//// + +Parameters + +Parameter Description +--------- ----------- +content_type The content type of the attached asset. For example, text/plain, image/jpeg. +org Organization UUID or organization name +app Application UUID or application name +collection Name or UUID of the collection of the entity the asset is attached to. +entity Name or UUID of the entity the asset is attached to. + +### Example request +The following request will retrieve the data for a jpeg file attached to an entity named 'cloud' in the 'pictures' collection: + + curl -X GET -H 'Accept: image/jpeg' 'https://api.usergrid.com/your-org/your-app/pictures/cloud + +## Retrieving an asset entity +To retrieve the entity that an asset is attached to, perform a ``GET`` request as you normally would to retrieve an entity. For more information, see [Retrieving Data Entities](../data-storage/entities.html#retrieving-data-entities). \ No newline at end of file diff --git a/content/docs/_sources/asset-and-files/uploading-assets.txt b/content/docs/_sources/asset-and-files/uploading-assets.txt new file mode 100644 index 0000000000..c5b836fb47 --- /dev/null +++ b/content/docs/_sources/asset-and-files/uploading-assets.txt @@ -0,0 +1,86 @@ +# Uploading assets + +With Usergrid, you can store and retrieve files and assets that hold data objects such as images, video, and audio content. + +Usergrid manages these objects as Asset entities. Optionally, you can use Folder entities to organize related assets. + +## Uploading assets +Assets can be any file type and can be attached to any entity. When an asset is uploaded, Usergrid will automatically detect the file metadata for the asset and save it in the associated entity as a ``file-metadata`` property. Only 1 asset can be attached to an entity. + +To attach an asset to an entity, do the following: + +### Request syntax + + curl -X POST -F name='' -F file=@ 'https://api.usergrid.com//// + +Parameters + +Parameter Description +--------- ----------- +filename A filename to associate with the asset. +file_location The location of the asset to be uploaded. +org Organization UUID or organization name +app Application UUID or application name +collection Name or UUID of the collection of the entity you want to attach the asset to. +entity Name or UUID of an existing entity you want to attach the asset to. + +### Example request + + curl -X POST -i -F name='clouds' -F file=@happy_clouds.jpg 'https://api.usergrid.com/your-org/your-app/pictures/' + +### Example response + +Notice the ``file-metadata`` property in the response. + + { + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/users", + "uri" : "https://api.usergrid.com/amuramoto/sandbox/pictures", + "entities" : [ { + "uuid" : "410b213a-b379-11e3-a0e5-9953085ea376", + "type" : "user", + "name" : "test", + "created" : 1395681911491, + "modified" : 1399069838919, + "name" : "clouds", + "file" : "fobnszewobnioerabnoiawegbrn\n", + "file-metadata" : { + "content-type" : "image/jpeg", + "etag" : "\"2e1db7299b0a667ed80e674a0ef9d653\"", + "last-modified" : 1399070010115, + "content-length" : 28, + "checksum" : "2e1db7299b0a667ed80e674a0ef9d653" + }, + "metadata" : { + "connecting" : { + "likes" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/connecting/likes" + }, + "path" : "/users/410b213a-b379-11e3-a0e5-9953085ea376", + "sets" : { + "rolenames" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/roles", + "permissions" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/permissions" + }, + "connections" : { + "follows" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/follows" + }, + "collections" : { + "activities" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/activities", + "devices" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/devices", + "feed" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/feed", + "groups" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/groups", + "roles" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/roles", + "following" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/following", + "followers" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/followers" + } + } + } ], + "timestamp" : 1399070009986, + "duration" : 441, + "organization" : "your-org", + "applicationName" : "your-app" + } + +## Updating assets +To update the data for an asset, perform the same request outlined above in 'Uploading assets' as a ``PUT`` request rather than a ``POST``. diff --git a/content/docs/_sources/assets-and-files/file-storage-configuration.txt b/content/docs/_sources/assets-and-files/file-storage-configuration.txt new file mode 100644 index 0000000000..c56265aff5 --- /dev/null +++ b/content/docs/_sources/assets-and-files/file-storage-configuration.txt @@ -0,0 +1,39 @@ +# File storage configuration + +Usergrid can store your assets either on your hard drive or in the Amazon S3 cloud. + +Local storage configuration +--- + +By default assets are stored in the temporary folder /tmp/usergrid +This can be changed by editing this file /stack/rest/src/main/resources/usergrid-rest-context.xml and replacing {usergrid.temp.files} by the wanted destination +```xml + + + +``` + +AwS S3 configuration +--- + +To use your AWS S3 storage you need to change the binaryStore classpath and add several constructor arguments in /stack/rest/src/main/resources/usergrid-rest-context.xml + +Some examples : +```xml + + + + + + +``` +the regionName field is not mandatory, this code is also valid +```xml + + + + + +``` + +The filesize is limited to 50GB but you need to keep in mind that the file has to be stored on the hard drive before being sended to Amazon. diff --git a/content/docs/_sources/assets-and-files/folders.txt b/content/docs/_sources/assets-and-files/folders.txt new file mode 100644 index 0000000000..7c425be05e --- /dev/null +++ b/content/docs/_sources/assets-and-files/folders.txt @@ -0,0 +1,85 @@ +# Folders + +## Linking a folder to an asset +In order to access the asset for the image in the folder, you need to link the folder to the asset. You can do that by issuing a POST request in the following format: + + POST /{org-uuid}/{app-uuid}/folders/{folder-uuid}/assets/{assets_id} + +where ``{folder-uuid}`` is the UUID of the folder, and ``{assets-uuid}`` is the UUID of the assets entity. + +Here’s how you could link the folder and the asset you created for the my-image.jpg image: + + POST https://api.usergrid.com/my-org/my-app/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets/9501cda1-2d21-11e2-b4c6-02e81ac5a17b + +In the response, you should see the assets entity for the image added to the folder: + + { + "action": "post", + "application": "3400ba10-cd0c-11e1-bcf7-12313d1c4491", + "params": {}, + "path": "/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets", + "uri": "https://api.usergrid.com/my-org/my-app/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets", + "entities": [ + { + "uuid": "9501cda1-2d21-11e2-b4c6-02e81ac5a17b", + "type": "asset", + "name": "my-image.jpg", + "created": 1352763303163, + "modified": 1352763303163, + "metadata": { + "path": "/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets/9501cda1-2d21-11e2-b4c6-02e81ac5a17b" + }, + "owner": "5c0c1789-d503-11e1-b36a-12313b01d5c1", + "path": "/myassets/asset1" + } + ], + "timestamp": 1352830448045, + "duration": 54, + "organization": "my-org”, + "applicationName": "my-app" + } + +## Retrieve list of folder assets +You can also request a list of the linked contents of the folder like this: + + GET https://api.usergrid.com/my-org/my-app/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets + +The response should look something like this: + + { + "action": "get", + "application": "3400ba10-cd0c-11e1-bcf7-12313d1c4491", + "params": { + "_": [ + "1352830364891" + ] + }, + "path": "/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets", + "uri": "https://api.usergrid.com/my-org/my-app/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets", + "entities": [ + { + "uuid": "7bf47435-2ac8-11e2-b4c6-02e81ac5a17b", + "type": "asset", + "name": "my-image.jpg", + "created": 1352505133598, + "modified": 1352507245108, + "checksum": "8e0cd3866ee20746c99e9a9825f38ad8", + "content-length": 11853, + "content-type": "image/jpeg", + "etag": "\"8e0cd3866ee20746c99e9a9825f38ad8\"", + "metadata": { + "connecting": { + "assets": "/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets/7bf47435-2ac8-11e2-b4c6-02e81ac5a17b/connecting/assets" + }, + "connection": "assets", + "path": "/folders/6640a601-2ac6-11e2-92c3-02e81ae640dc/assets/7bf47435-2ac8-11e2-b4c6-02e81ac5a17b" + }, + "owner": "5c0c1789-d503-11e1-b36a-12313b01d5c1", + "path": "my-image" + } + ], + "timestamp": 1352830363797, + "duration": 57, + "organization": "my-org", + "applicationName": "my-app" + } diff --git a/content/docs/_sources/assets-and-files/legacy-asset-support.txt b/content/docs/_sources/assets-and-files/legacy-asset-support.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/content/docs/_sources/assets-and-files/retrieving-assets.txt b/content/docs/_sources/assets-and-files/retrieving-assets.txt new file mode 100644 index 0000000000..9313ae8398 --- /dev/null +++ b/content/docs/_sources/assets-and-files/retrieving-assets.txt @@ -0,0 +1,27 @@ +# Retrieving assets + +## Retrieving asset data + +To retrieve the asset from an entity, send a ``GET`` request with the ``Accept`` header set to the content type of the asset. The content type can be retrieved from the ``file-metadata.content-type`` property of the entity the asset is attached to. + +### Request syntax + + curl -X GET -H 'Accept: ' 'https://api.usergrid.com//// + +Parameters + +Parameter Description +--------- ----------- +content_type The content type of the attached asset. For example, text/plain, image/jpeg. +org Organization UUID or organization name +app Application UUID or application name +collection Name or UUID of the collection of the entity the asset is attached to. +entity Name or UUID of the entity the asset is attached to. + +### Example request +The following request will retrieve the data for a jpeg file attached to an entity named 'cloud' in the 'pictures' collection: + + curl -X GET -H 'Accept: image/jpeg' 'https://api.usergrid.com/your-org/your-app/pictures/cloud + +## Retrieving an asset entity +To retrieve the entity that an asset is attached to, perform a ``GET`` request as you normally would to retrieve an entity. For more information, see [Retrieving Data Entities](../data-storage/entities.html#retrieving-data-entities). \ No newline at end of file diff --git a/content/docs/_sources/assets-and-files/uploading-assets.txt b/content/docs/_sources/assets-and-files/uploading-assets.txt new file mode 100644 index 0000000000..c5b836fb47 --- /dev/null +++ b/content/docs/_sources/assets-and-files/uploading-assets.txt @@ -0,0 +1,86 @@ +# Uploading assets + +With Usergrid, you can store and retrieve files and assets that hold data objects such as images, video, and audio content. + +Usergrid manages these objects as Asset entities. Optionally, you can use Folder entities to organize related assets. + +## Uploading assets +Assets can be any file type and can be attached to any entity. When an asset is uploaded, Usergrid will automatically detect the file metadata for the asset and save it in the associated entity as a ``file-metadata`` property. Only 1 asset can be attached to an entity. + +To attach an asset to an entity, do the following: + +### Request syntax + + curl -X POST -F name='' -F file=@ 'https://api.usergrid.com//// + +Parameters + +Parameter Description +--------- ----------- +filename A filename to associate with the asset. +file_location The location of the asset to be uploaded. +org Organization UUID or organization name +app Application UUID or application name +collection Name or UUID of the collection of the entity you want to attach the asset to. +entity Name or UUID of an existing entity you want to attach the asset to. + +### Example request + + curl -X POST -i -F name='clouds' -F file=@happy_clouds.jpg 'https://api.usergrid.com/your-org/your-app/pictures/' + +### Example response + +Notice the ``file-metadata`` property in the response. + + { + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/users", + "uri" : "https://api.usergrid.com/amuramoto/sandbox/pictures", + "entities" : [ { + "uuid" : "410b213a-b379-11e3-a0e5-9953085ea376", + "type" : "user", + "name" : "test", + "created" : 1395681911491, + "modified" : 1399069838919, + "name" : "clouds", + "file" : "fobnszewobnioerabnoiawegbrn\n", + "file-metadata" : { + "content-type" : "image/jpeg", + "etag" : "\"2e1db7299b0a667ed80e674a0ef9d653\"", + "last-modified" : 1399070010115, + "content-length" : 28, + "checksum" : "2e1db7299b0a667ed80e674a0ef9d653" + }, + "metadata" : { + "connecting" : { + "likes" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/connecting/likes" + }, + "path" : "/users/410b213a-b379-11e3-a0e5-9953085ea376", + "sets" : { + "rolenames" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/roles", + "permissions" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/permissions" + }, + "connections" : { + "follows" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/follows" + }, + "collections" : { + "activities" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/activities", + "devices" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/devices", + "feed" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/feed", + "groups" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/groups", + "roles" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/roles", + "following" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/following", + "followers" : "/users/410b213a-b379-11e3-a0e5-9953085ea376/followers" + } + } + } ], + "timestamp" : 1399070009986, + "duration" : 441, + "organization" : "your-org", + "applicationName" : "your-app" + } + +## Updating assets +To update the data for an asset, perform the same request outlined above in 'Uploading assets' as a ``PUT`` request rather than a ``POST``. diff --git a/content/docs/_sources/counters-and-events/creating-and-incrementing-counters.txt b/content/docs/_sources/counters-and-events/creating-and-incrementing-counters.txt new file mode 100644 index 0000000000..3bf7f57b1d --- /dev/null +++ b/content/docs/_sources/counters-and-events/creating-and-incrementing-counters.txt @@ -0,0 +1,74 @@ +## Creating & incrementing counters +To create a new counter or increment an existing counter, include the counter property in the body of a POST to the /events endpoint. More than one counter can be incremented in the same request. + +__Note__: It may take up to 30 seconds after an event has been posted for the counter to be incremented. + +### Request syntax + + curl -X POST https://api.usergrid.com///events -d '{"timestamp":, "counters" : {:}}' + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +timestamp A required UNIX timestamp that specifies the time the counter is being incremented. +counter_name The name of the counter to create or the existing counter to increment. +increment_value The value to increment the counter by. + +Regarding the ``increment_value``, a negative number can be specified to decrement the value. A value of '0' can be specified to reset the value of the counter. + +For the ``timestamp``, specifying a value of 0 will automatically assign the current time. + +### Example request +The following request will increment the 'button_clicks' counter by one, with a timestamp of the current time. + + curl -X POST https://api.usergrid.com/your-org/your-app/events -d '{"timestamp":0, "counters" : {"button_clicks":1}}' + +### Example response + + { + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/events", + "uri" : "https://api.usergrid.com/your-org/your-app/events", + "entities" : [ { + "uuid" : "b11217fc-9d3a-1427-b24e-699740088e05", + "type" : "event", + "created" : 1401224590293, + "modified" : 1401224590293, + "timestamp" : 1401224590293, + "counters" : { + "button_clicks" : 1 + }, + "message" : null, + "metadata" : { + "path" : "/events/b11217fc-9d3a-1427-b24e-699740088e05" + } + } ], + "timestamp" : 1401224590291, + "duration" : 30, + "organization" : "your-org", + "applicationName" : "your-app" + } + +## Decrementing/resetting counters +To decrement a counter, specify a negative number for the counter value in any of the above examples. + +To reset a counter, specify a value of 0 for the counter value in any of the above examples. + +Note that the Usergrid JavaScript SDK also provides dedicated methods for decrementing and resetting counters. + +## Using counters hierarchically + +You can organize counters into hierarchies by giving them dot-separated names, e.g. ``button_clicks.homepage``. Incrementing a counter lower in a hierarchy increments all of the counters upward in the hierarchy chain. + +For example, you want to log errors that your app generates, so you create hierarchical counters for each module and function within that module. In this example, you create the following set of counters: + + errors + errors.module + errors.module.function + +Incrementing ``errors.module.function`` by 1 increments all three counters by 1. A hierarchy can be a useful way of easily tracking actions in your app at both a cumulative and granular level. \ No newline at end of file diff --git a/content/docs/_sources/counters-and-events/events-and-counters.txt b/content/docs/_sources/counters-and-events/events-and-counters.txt new file mode 100644 index 0000000000..cbb0b93007 --- /dev/null +++ b/content/docs/_sources/counters-and-events/events-and-counters.txt @@ -0,0 +1,8 @@ +# Counters & events +Counters can be used to track statistics on many aspects of an application by keeping a running count of the number of times an action occurs in your app. Posting an event increments the counter. Counters can also be retrieved by time period, allowing you to generate reports on specific actions in your app. + +With Usergrid, you can define your own counters. Some of the things that you might track with a user-defined counter are: + +* How many times people click on the help button in your application. +* How many times your game is played each day. +* How many times your banner ads are clicked each day. diff --git a/content/docs/_sources/counters-and-events/retrieving-counters.txt b/content/docs/_sources/counters-and-events/retrieving-counters.txt new file mode 100644 index 0000000000..52109529ed --- /dev/null +++ b/content/docs/_sources/counters-and-events/retrieving-counters.txt @@ -0,0 +1,109 @@ +# Retrieving counters +To retrieve a counter, do the following: + +## Request syntax + + curl -X GET https://api.usergrid.com/counters?counter= + +Parameters + +Parameter Description +--------- ----------- +counter_name The name of the counter to be retrieved. + +More than one counter can be retrieved with a single request by appending additional counter parameters to the request URI. + +## Example request + + curl -X GET https://api.usergrid.com/my-org/my-app/counters?counter=button_clicks + +## Example response + + { + "action" : "get", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { + "counter" : [ "button_clicks" ] + }, + "uri" : "https://api.usergrid.com/your-org/your-app", + "entities" : [ ], + "timestamp" : 1401310084096, + "duration" : 21, + "organization" : "your-org", + "applicationName" : "your-app", + "count" : 0, + "counters" : [ { + "name" : "button_clicks", + "values" : [ { + "timestamp" : 1, + "value" : 9 + } ] + } ] + } + +## Retrieving counters by time interval +Knowing the value of a counter is useful; however, you often need to know how the value varies over time. Fortunately, the API provides a method for you to view this data over any time interval or level of granularity. + +For example, let’s say you’re incrementing a counter every time someone launches your application. You might be interested in which days of the week the application sees the most usage. Using the API, you can examine the counter over a set of weeks, with the data split into daily intervals. Using this information, you can see which are your peak days of usage. You can also view usage across a single day, so you can see if your application is used more in the mornings or the evenings. + +## Request syntax + + curl -X GET https://api.usergrid.com/counters?start_time=&end_time=&resolution=&counter= + +Parameters + +Parameter Description +--------- ----------- +start_time The beginning of the time period to search +end_time The end of the time period to search +resolution The interval at which counters are displayed. +counter_name The name of the counter to be retrieved. + +The following resolutions are supported: + +* all +* minute +* five_minutes +* half_hour +* hour +* six_day +* day +* week +* month + +For example, if the interval is day, and the start time and end time values span 4 days, you will get aggregate counts for each of the 4 days. + +## Example request + +For example, to retrieve a time range of values, with a granularity of "day", for a counter called "button_clicks", the GET request would look like this: + + curl -X GET https://api.usergrid.com/my-org/my-app/counters?start_time=1315119600000&end_time=1315724400000&resolution=day&counter=button_clicks + +## Example response + + { + action: "get", + uri: "http://api.usergrid.com/438a1ca1-cf9b-11e0-bcc1-12313f0204bb/counters", + timestamp: 1315354369272, + duration: 28, + counters: [ + { + name: "button_clicks", + values: [ + { + value: 2 + timestamp: 1315180800000 + }, + { + value: 1 + timestamp: 1315267200000 + }, + { + value: 1 + timestamp: 1315353600000 + } + ] + } + ] + } + \ No newline at end of file diff --git a/content/docs/_sources/data-queries/advanced-query-usage.txt b/content/docs/_sources/data-queries/advanced-query-usage.txt new file mode 100644 index 0000000000..4b78215715 --- /dev/null +++ b/content/docs/_sources/data-queries/advanced-query-usage.txt @@ -0,0 +1,23 @@ +# Advanced query usage + +

Note


 +Query examples in this content are shown unencoded to make them easier to read. Keep in mind that you might need to encode query strings if you're sending them as part of URLs, such as when you're executing them with the cURL tool. +

+ +## Attaching a query to all API calls + + +

Note


 +

JavaScript SDK only.

+In some cases, it may be convenient to attach a query or other URI parameter to every call you make to Usergrid, such as a custom identifier or token. To do this with the Usergrid JavaScript SDK, add a qs property to your Usergrid.Client object when you initialize the SDK. For more on initializing the SDK, see our install guide. +

+ +For example, the following would append ?custom_id=1234 to every call sent from the Usergrid JavaScript SDK to Usergrid: + + var options = { + orgName:'yourOrg', + appName:'yourApp', + qs:'custom_id=1234' + } + var dataClient = new Usergrid.Client(options); + diff --git a/content/docs/_sources/data-queries/operators-and-types.txt b/content/docs/_sources/data-queries/operators-and-types.txt new file mode 100644 index 0000000000..8c0bb6a331 --- /dev/null +++ b/content/docs/_sources/data-queries/operators-and-types.txt @@ -0,0 +1,135 @@ +# Query operators & data types + +The following operators and data types are supported by the SQL-like query language in Usergrid. + +## Operators + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OperatorPurposeExample
'<' or 'lt'Less thanselect * where quantity > '1000'
'<=' or 'lte'Less than or equal toExample
'=' or 'eq'Equalsselect * where price = '20.00'
'>=' or 'gte'Greater than or equal to select * where quantity >= '1000'
'>' or 'gt'Greater thanselect * where quantity > '1000'
not Subtraction of resultsselect * where quantity < '4000' and not quantity = '2000'
containsNarrow by contained textselect * where title contains 'tale'
andUnion of resultsselect * where quantity > '1000' and quantity < '4000'
orIntersection of resultsselect * where quantity = '1000' or quantity = '4000'
+ + +### Precedence + +The operators at the bottom of the above table are the ones with lower precedence. +When a query is evaluated the comparison operators (=, > , <, <= and >=) will be evaluated first. +And next "not", "contains" and "or" will be evaluated and in that order. + +Though they are not shown above, parentheses are allowed and may be used to group query expressions. + +For example, given our rules of precedence, these two queries are equivalent: + + select * where age > 6 or size = 'large' and color = 'tabby' + + select * where (age > 6 or size = 'large') and color = 'tabby' + + +## Data types + +As you develop queries, remember that entity properties each conform to a particular data type. For example, in the default entity User, the name property is stored as a string, the created date as a long, and metadata is stored as a JSON object. Your queries must be data type-aware to ensure that query results are as you expect them to be. + +For example, if you create an entity with a price property with a value of 100.00, querying for 100 will return no results, since the API expected a decimal-delimited float value in your query. + +For a list of property data types for each default entities, see [Default Data Entities](../rest-endpoints/api-doc.html#models)s. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
string
'value', unicode '\uFFFF', octal '\0707'
long
1357412326021

Timestamps are typically stored as long values.
float
10.1, -10.1, 10e10, 10e-10, 10E10, 10E-10

+ Your query must be specific about the value you're looking for, down to the value + (if any) after the decimal point.
boolean
true | false
UUID
ee912c4b-5769-11e2-924d-02e81ac5a17b
Array
["boat", "car", "bike"]
object

For a JSON object like this one:

+
+                {
+                 "items": [
+                  {
+                   "name": "rocks"
+                  },
+                  {
+                   "name": "boats"
+                  }
+                 ]
+                }
+            
+

you can use dot notation to reach property values in the object:

+
+                 /mycollection/thing?ql="select * where items.name = 'rocks'"
+            
+

Objects are often used to contain entity metadata, such as the activities + associated with a user, the users associated with a role, and so on.

+

Please note that object properties are not indexed. This means queries + using dot-notation will be much slower than queries on indexed entity properties.

diff --git a/content/docs/_sources/data-queries/query-language.txt b/content/docs/_sources/data-queries/query-language.txt new file mode 100644 index 0000000000..a491740b3a --- /dev/null +++ b/content/docs/_sources/data-queries/query-language.txt @@ -0,0 +1,427 @@ +# Query Language + +> Query examples in this content are shown unencoded to make +> them easier to read. Keep in mind that you might need to encode query +> strings if you're sending them as part of URLs, such as when you're +> executing them with the cURL tool. + +The following example retrieves a list of restaurants (from a +restaurants collection) whose name property contains the value "diner", +sorting the list in ascending order by name: + + /restaurants?ql=select * where name contains 'diner' order by name asc + + +## Basic syntax + +Queries of Usergrid data for Apache Usergrid are made up of two kinds of +statements: the path to the collection you want to query, followed by +the query language statement containing your query. These two statements +are separated by "?ql=" to indicate where the query language statement +starts. + +To retrieve items from a collection, you would use a syntax such as the +following: + + /?ql= + +In the following example, the query is retrieving all users whose name +is Gladys Kravitz. + + /users?ql=select * where name = 'Gladys Kravitz' + +The following example selects all items except those that have an a +property value of 5: + + /items?ql=select * where NOT a = 5 + +Note that there is a shortcut available when your query selects all +items matching certain criteria -- in other words, where you use a +statement that starts "select \* where". In this case, you can omit the +first part of the statement and abbreviate it this way: + + /items?ql=NOT a = 5 + +You query your Apache Usergrid data by using a query syntax that's like +Structured Query Language (SQL), the query language for relational +databases. Unlike a relational database, where you specify tables and +columns containing the data you want to query, in your Apache Usergrid +queries you specify collections and entities. + +The syntax of Apache Usergrid queries only *resembles* SQL to +make queries familiar and easier to write. However, the language isn't +SQL. Only the syntax items documented here are supported. + +## Supported operators + +Comparisons + +* Less than `<` or `lt` +* Less than or equal `<=` or `lte` +* Equal `=` or `eq` +* Greater than or equal `>=` or `gte` +* Greater than `>` or `gt` +* Not equal `NOT` + +Logical operations + +* Intersection of results `and` +* Union of results `or` +* Subtraction of results `not` + + +## Query Response Format + +the query’s response is formatted in +JavaScript Object Notation (JSON). This is a common format used for +parameter and return values in REST web services. + +So for the following query: + + /users?ql=select * where name = ‘Gladys Kravitz’ + +...you would get a response such as the the one below. The JSON format +arranges the data in name/value pairs. Many of the values correspond to +specifics of the request, including the request’s HTTP action (GET), the +application’s UUID, the request’s parameters (the query string you +sent), and so on. + +Here, the query is asking for whole entities in the users collection. +Data corresponding to the response is captured in the response’s +`entities` array. The array has one member here, corresponding to the +one user found by the query (another kind of query might have found more +users). That one member gives the UUID of the entity (user), the entity +type, and values for properties such as name, username, email, and so +on. + +```json +{ + "action" : "get", + "application" : "8272c9b0-d86a-11e2-92e2-cdf1ce04c1c0", + "params" : { + "ql" : [ "select * where name = 'Gladys Kravitz'" ] + }, + "path" : "/users", + "uri" : "http://api.usergrid.com/myorg/myapp/users", + "entities" : [ { + "uuid" : "d0d7d0ba-e97b-11e2-8cef-411c466c4f2c", + "type" : "user", + "name" : "Gladys Kravitz", + "created" : 1373472876859, + "modified" : 1373472876859, + "username" : "gladys", + "email" : "gladys@example.com", + "activated" : true, + "picture" : "http://www.gravatar.com/avatar/20c57d4f41cf51f2db44165eb058b3b2", + "metadata" : { + "path" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c", + "sets" : { + "rolenames" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/rolenames", + "permissions" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/permissions" + }, + "connections" : { + "firstname" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/firstname", + "lastname" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/lastname" + }, + "collections" : { + "activities" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/activities", + "devices" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/devices", + "feed" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/feed", + "groups" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/groups", + "roles" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/roles", + "following" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/following", + "followers" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/followers" + } + } + } ], + "timestamp" : 1374694196061, + "duration" : 48, + "organization" : "myorg", + "applicationName" : "myapp", + "count" : 1 +} +``` + +Compare the preceding example with the following for another kind of +query. Imagine the following request string, where the query string is +asking for only the values of two of the entity’s properties (username +and name): + + /users?ql=select username,name where name=’Gladys Kravitz’ + +In the response JSON from this query, the return value is specified as +the property of the `list` item -- here, an array containing only the +values of the properties the query asked for, in the order they were +requested (username first, then name). + + { + "action" : "get", + "application" : "8272c9b0-d86a-11e2-92e2-cdf1ce04c1c0", + "params" : { + "ql" : [ "select username,name where name='Gladys Kravitz'" ] + }, + "path" : "/users", + "uri" : "http://api.usergrid.com/myorg/myapp/users", + "list" : [ [ "gladys", "Gladys Kravitz" ] ], + "timestamp" : 1374697463190, + "duration" : 25, + "organization" : "myorg", + "applicationName" : "myapp", + "count" : 1 + } + + +## Data types supported in queries + +As you develop queries for your Apache Usergrid data, remember that entity +properties each conform to a particular data type (whether the entity is +included by default or an entity you defined). Your queries must +acknowledge this, testing with values that conform to each property's +data type. (You can view the list of property data types for the default +entities at [Default Data Entities](/default-data-entities).) + +For example, in the default entity `User`, the `name` property is stored +as a `string`, the created date as a `long`, and metadata is stored as a +JSON object. Your queries must be data type-aware so that you can be +sure that query results are as you expect them to be. + +So imagine you define an entity with a `price` property whose value +might be `100.00`. Querying for `100` will return no results even if +there are occurrences of `100.00` as `price` values in your data set. +That's because the database expected a decimal-delimited `float` value +in your query. + + +Data Type Examples Notes +----------- ------------------------------------------------------------------------------------------- --------- +`string` `'value'`, `unicode '\uFFFF'`, `octal '\0707'` true | false +`long` 1357412326021 Timestamps are typically stored as `long` values. +`float` 10.1, -10.1, 10e10, 10e-10, 10E10, 10e-10 Your query must be specific about the value you're looking for, down to the value (if any) after the decimal point. +`boolean` true | false +`UUID` ee912c4b-5769-11e2-924d-02e81ac5a17b UUID types are typically used for the unique IDs of entities. The value must conform to the following format (do not enclose with quotation marks): xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + +`object` For a JSON object like this one: + +``` + { + "items":[ + {"name":"rocks"}, + {"name":"boats"} + ] + } +``` + +you can use dot notation to reach property values in the object: /mycollection/thing?ql="select * where items.name = 'rocks'" Objects are often used to contain entity metadata, such as the activities associated with a user, the users associated with a role, and so on. + +## Retrieving values for multiple properties + +Your query can return multiple kinds of values -- such as the values of +multiple properties -- by specifying the property names in your select +statement as a comma-separated list. + +For example, the following request returns the address and phone number +of users whose name is Gladys Kravitz: + + /users?ql=select address,phone_number where name = 'Gladys Kravitz' + + +## Querying for the contents of text + +Your query can search the text of entity values of the string data type. +For example, you can search a postal code field for values that start +with a specific three numbers. + +For example, the following query selects all restaurants with the word +`diner` in the name: + + /restaurants?ql=select * where name contains 'diner' + +**Note:** Not all string properties of the default entities are +indexed for searching. This includes the `User` entity's `username` +property. + +This will return all users whose name property contains the word 'Kravitz' + + /users?ql=select * where name contains 'Kravitz' + +This will return all users whose name property contains a word beginning with 'Krav' + + /users?ql=select * where name contains 'Krav*' + +This will return all users whose name is exactly 'Gladys Kravitz' + + /users?ql=select * where name = 'Gladys Kravitz' + + +## Sorting results + +You can return query results that are sorted in the order you specify. +Use the `order by` clause to specify the property to sort by, along with +the order in which results should be sorted. The syntax for the clause +is as follows `order by asc | desc` + +The following table includes a few examples: + + /users?ql=select * where lastname = 'Smith' order by firstname asc + + + /users?ql=select * where lastname = 'Smith' order by firstname desc + + + /users?ql=select * where lastname contains 'Sm*' order by lastname asc, firstname asc + + +## Geoqueries + +Many of today's apps are enhanced by the use of *geolocation*, wireless +detection of the physical location of a remote device. These apps are +said to be *geolocation-aware* in that they query the device to +determine the user's position and then use this data to further enhance +the user's experience. For example, apps can capture the exact location +where a picture was taken or a message was created. + +Usergrid support geolocation on any entity, both built in (e.g., +users, groups) and user defined. + +To add a location to any entity, include the following member to the +JSON in a POST or PUT call: + + "location": { + "latitude": 37.779632, + "longitude": -122.395131 + } + +For example, to store a listing of restaurants and their locations, +start by creating a collection called restaurants: + + POST https://api.usergrid.com/org_name/app_name/restaurants + +Next, add a new entity to the collection: + + POST https://api.usergrid.com/org_name/app_name/restaurants + { + "name": "Rockadero", + "address": "21 Slate Street, Bedrock, CA", + "location": { + "latitude": 37.779632, + "longitude": -122.395131 + } + } + +This creates a new restaurant entity called "Rockadero" with the +longitude and latitude included as part of the object. + +When a location is added to an entity, it is easy to make queries +against that data. For example, to see all restaurants within a 10 mile +radius of the user's location, make a GET call against that entity, and +include a search query in the following format: + + location within of , + +If we use the location of our user Fred, we first need to convert miles +to meters. 1 mile is equivalent to 1609.344 meters, so 10 miles is about +16093 meters. Thus, the API call looks like this: + + GET https://api.usergrid.com/org_name/app_name/restaurants?ql=location within 16093 of 37.776753, -122.407846 + + +## Managing large sets of results + +When your query might return more results than you want to display to +the user at once, you can use the limit parameter with cursors or API +methods to manage the display of results. By default, query results are +limited to 10 at a time. You can adjust this by setting the limit +parameter to a value you prefer. + +For example, you might execute a query that could potentially return +hundreds of results, but you want to display 20 of those at a time to +users. To do this, your code sets the limit parameter to 20 when +querying for data, then provides a way for the user to request more of +the results when they're ready. + +You would use the following parameters in your query: + ++-------------------------+-------------------------+-------------------------+ +| Parameter | Type | Description | ++=========================+=========================+=========================+ +| `limit` | integer | Number of results to | +| | | return. The maximum | +| | | number of results is | +| | | 1,000. Specifying a | +| | | limit greater than | +| | | 1,000 will result in a | +| | | limit of 1,000. | +| | | | +| | | Limit is applied to the | +| | | collection, not the | +| | | query string. For | +| | | example, the following | +| | | query will find the | +| | | first 100 entities in | +| | | the books collection, | +| | | then from that set | +| | | return the ones with | +| | | author='Hemingway': | +| | | | +| | | /books?ql=author = | +| | | 'Hemingway'&limit=100 | +| | | | +| | | You can also use the | +| | | limit parameter on a | +| | | request without a query | +| | | string. The following | +| | | example is shorthand | +| | | for selecting all books | +| | | and limiting by 100 at | +| | | a time: | +| | | | +| | | /books?limit=100 | +| | | | +| | | Using a limit on a | +| | | DELETE can help you | +| | | manage the amount of | +| | | time it takes to delete | +| | | data. For example you | +| | | can delete all of the | +| | | books, 1000 at a time, | +| | | with the following: | +| | | | +| | | DELETE /books?limit | +| | | =1000 | +| | | | +| | | Keep in mind that | +| | | DELETE operations can | +| | | take longer to execute. | +| | | Yet even though the | +| | | DELETE query call might | +| | | time out (such as with | +| | | a very large limit), | +| | | the operation will | +| | | continue on the server | +| | | even if the client | +| | | stops waiting for the | +| | | result. | ++-------------------------+-------------------------+-------------------------+ +| `cursor` | string | An encoded | +| | | representation of the | +| | | query position pointing | +| | | to a set of results. To | +| | | retrieve the next set | +| | | of results, pass the | +| | | cursor with your next | +| | | call for most results. | ++-------------------------+-------------------------+-------------------------+ + +For example: + +Select all users whose name starts with fred, and returns the first 50 +results: + + /users?ql=select * where name = 'fred*'&limit=50 + +Retrieve the next batch of users whose name is "fred", passing the +cursor received from the last request to specify where the next set of +results should begin: + + /users?ql=select * where name = 'fred*'&limit=50&cursor=LTIxNDg0NDUxNDpnR2tBQVFFQWdITUFDWFJ2YlM1emJXbDBhQUNBZFFBUUQyMVZneExfRWVLRlV3TG9Hc1doZXdDQWRRQVFIYVdjb0JwREVlS1VCd0xvR3NWT0JRQQ diff --git a/content/docs/_sources/data-queries/query-parameters.txt b/content/docs/_sources/data-queries/query-parameters.txt new file mode 100644 index 0000000000..944c27b0f9 --- /dev/null +++ b/content/docs/_sources/data-queries/query-parameters.txt @@ -0,0 +1,153 @@ +# Query parameters & clauses + +When querying your data, you can use your query string to get the data, then sort and manage it on the client. This topic describes a few techniques. + +Query examples in this content are shown unencoded to make them easier to read. Keep in mind that you might need to encode query strings if you're sending them as part of URLs, such as when you're executing them with the cURL tool. + +

Note


 +Optimizing queries. As a best practice, you should include no more than 3 parameters in your queries. The API will not prevent you from submitting a query with more than 3 parameters; however, due to the nature of NoSQL, queries with many parameters can quickly become very inefficient. +

+ +For more information, see our [Usergrid DBMS overview](../data-store/data-storage-dbms.html) and [Data store best practices](../data-storage/optimizing-access). + +### Contains + +Your query can search the text of entity values of the string data type. For example, you can search a postal code field for values that start with a specific three numbers. + +For example, the following query selects all restaurants with the word diner in the name: + + /restaurants?ql=select * where restaurants contains 'diner' + +__Note__: Not all string properties of the default entities are indexed for searching. This includes the User entity's username property. + +The following table lists a few examples of the kind of searches you can do in queries. + + + + + + + + + + + + + + + + + + + + + + +
GoalExampleNotes
Find books whose 'title' property contains the full word "tale".
/books?ql=select * where title contains 'tale'
containslooks for the occurrence of a full word anywhere in the searched property. Note that contains will not work on the 'name' property, since it is not full-text indexed in the database.
Find books whose 'title' property contains a word that starts with "ta".
/books?ql=select * where title contains 'ta*'
containswill look for partial words if you include a wildcard.
Find books whose title property is exactly and only "A Tale of Two Cities".
/books?ql=select * where title = 'A Tale of Two Cities'
The = operator is looking for a match in the entire searched property value. Use a * wildcard to look for some set of the first characters only.
+ + +### Location + +If you've stored location data with your entities, you can query for the proximity of the geographical locations those entities represent. For more information on geolocation, see [Geolocation](../geolocation/geolocation.html). + + + + + + + + + + + + +
GoalExampleNotes
Find stores whose locations are within the specified longitude and latitude.
/stores?ql=location within 500 of 40.042016, -86.900749
within will test for values within the value you specify. The within value is expressed as a number of meters.
The return results are sorted in order of nearest to furthest. If there are multiple entries at the same location, they're returned in the order they were added to the database.
For more on geolocation queries, see Geolocation.
+ +### Order by + +You can return query results that are sorted in the order you specify. Use the order by clause to specify the property to sort by, along with the order in which results should be sorted. The syntax for the clause is as follows: + + order by asc | desc + +The following table includes a few examples: + + + + + + + + + + + + + + + + + + +
GoalExample
Sort by first name in ascending order/users?ql=select * where lastname = 'Smith' order by firstname asc
Sort by first name in descending order/users?ql=select * where lastname = 'Smith' order by firstname desc
Sort by last name, then first name in ascending orderl/users?ql=select * where lastname contains 'Sm*' order by lastname asc, firstname asc
+ + +### Limit + +When your query might return more results than you want to display to the user at once, you can use the limit parameter with cursors or API methods to manage the display of results. By default, query results are limited to 10 at a time. You can adjust this by setting the limit parameter to a value you prefer. + +For example, you might execute a query that could potentially return hundreds of results, but you want to display 20 of those at a time to users. To do this, your code sets the limit parameter to 20 when querying for data, then provides a way for the user to request more of the results when they're ready. + +You would use the following parameters in your query: + +
+ + + + + + + + + + +
ParameterTypeDescription
limitinteger

Number of results to return. The maximum number of results is 1,000. + Specifying a limit greater than 1,000 will result in a limit of 1,000.

+

You can also use the limit parameter on a request without a query string. + The following example is shorthand for selecting all books and limiting by 100 at a time:

+
/books?limit=100
+

Using a limit on a DELETE can help you manage the amount of time it takes + to delete data. For example you can delete all of the books, 1000 at a time, + with the following:

+
DELETE /books?limit=1000
+

Keep in mind that DELETE operations can take longer to execute. + Yet even though the DELETE query call might time out (such as with a + very large limit), the operation will continue on the server even if + the client stops waiting for the result.

+
+ +For example: + +Select all users whose name starts with fred, and returns the first 50 results: + + /users?ql=select * where name = 'fred*'&limit=50 + + +### Cursor + + + + + + + + + + + +
ParameterTypeDescription
cursorstringAn encoded representation of the query position pointing to a set of results. To retrieve the next set of results, pass the cursor with your next call for most results./td> +
+ +Retrieve the next batch of users whose name is "fred", passing the cursor received from the last request to specify where the next set of results should begin: + + /users?ql=select * where name = 'fred*'&limit=50&cursor=LTIxNDg0NDUxNDpVdjb0JwREVlS1VCd0xvR3NWT0JRQQ + \ No newline at end of file diff --git a/content/docs/_sources/data-queries/querying-your-data.txt b/content/docs/_sources/data-queries/querying-your-data.txt new file mode 100644 index 0000000000..2da961d90a --- /dev/null +++ b/content/docs/_sources/data-queries/querying-your-data.txt @@ -0,0 +1,121 @@ +# Querying your data + +This article describes how to use queries to filter data retrieved from your backend data store. Queries allow you to work with only the data you need, making your app more efficient and manageable by reducing the number of entities returned or acted on by the API. A query can be sent with any GET, PUT or DELETE request. For example, you might query the API to retrieve only the user entities with the property status:'active' to get a list of your users that have active accounts. + +For information on more advanced query usage and syntax, see [Query parameters & clauses](query-parameters.html). + +

Note


 +Query examples in this content are shown unencoded to make them easier to read. Keep in mind that you might need to encode query strings if you're sending them as part of URLs, such as when you're executing them with the cURL tool. +

+ +## Basic query usage + +The following examples show how to query the Usergrid API to return the first 5 entities in the users collection that contain the property status:'active'. + +

Note


 +Optimizing queries: As a best practice, you should include no more than 3 parameters in your queries. The API will not prevent you from submitting a query with more than 3 parameters; however, due to the nature of NoSQL, queries with many parameters can quickly become very inefficient. +

+ +For more information, see our [Usergrid DBMS overview](../data-store/data-storage-dbms.html) and [Data store best practices](../data-storage/optimizing-access). + +### Request Syntax + + https://api.usergrid.com///?ql= + +Note: Any values specified in the query statement should be enclosed in single-quotes. + + https://api.usergrid.com/your-org/your-app/users?limit=5&ql=select * where status = 'active' + +Alternatively, when you use a statement that starts select * where you can omit the first part of the statement and abbreviate it this way: + + https://api.usergrid.com/your-org/your-app/users?limit=5&ql=status = 'active' + +### Retrieving values for multiple properties + +Your query can return multiple kinds of values -- such as the values of multiple properties -- by specifying the property names in your select statement as a comma-separated list. + +For example, the following request returns the address and phone number of users whose name is Gladys Kravitz: + + /users?ql=select address,phone_number where name = 'Gladys Kravitz' + +### Response syntax + +When you query your data, the API response is formatted in JavaScript Object Notation (JSON). This is a common format used for parameter and return values in REST web services. + +Data corresponding to the response is captured in the response’s entities array. The array will include one JSON-object for each entity returned for the query. Each returned entity will include a number of default properties, including the UUID of the entity, the entity type, and values for properties such as name, username, email, and so on. For a complete list of default properties by entity type, see [Default Data Entities](../rest-endpoints/api-doc.html#models). + +For example, the following query for all entities of type user where the name property equals 'Gladys Kravitz': + + /users?ql=select * where name = ‘Gladys Kravitz’ + +will return the following response: + + { + "action" : "get", + "application" : "8272c9b0-d86a-11e2-92e2-cdf1ce04c1c0", + "params" : { + "ql" : [ "select * where name = 'Gladys Kravitz'" ] + }, + "path" : "/users", + "uri" : "http://api.usergrid.com/myorg/myapp/users", + "entities" : [ { + "uuid" : "d0d7d0ba-e97b-11e2-8cef-411c466c4f2c", + "type" : "user", + "name" : "Gladys Kravitz", + "created" : 1373472876859, + "modified" : 1373472876859, + "username" : "gladys", + "email" : "gladys@example.com", + "activated" : true, + "picture" : "http://www.gravatar.com/avatar/20c57d4f41cf51f2db44165eb058b3b2", + "metadata" : { + "path" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c", + "sets" : { + "rolenames" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/rolenames", + "permissions" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/permissions" + }, + "connections" : { + "firstname" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/firstname", + "lastname" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/lastname" + }, + "collections" : { + "activities" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/activities", + "users" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/users", + "feed" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/feed", + "groups" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/groups", + "roles" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/roles", + "following" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/following", + "followers" : "/users/d0d7d0ba-e97b-11e2-8cef-411c466c4f2c/followers" + } + } + } ], + "timestamp" : 1374694196061, + "duration" : 48, + "organization" : "myorg", + "applicationName" : "myapp", + "count" : 1 + } + +Compare the preceding example with the following for another kind of query. Imagine the following request string, where the query string is asking for only the values of two of the entity’s properties (username and name): + + /users?ql=select username,name where name=’Gladys Kravitz’ + +In the response JSON from this query, the return value is specified as the property of the list item -- here, an array containing only the values of the properties the query asked for, in the order they were requested (username first, then name). + + { + "action" : "get", + "application" : "8272c9b0-d86a-11e2-92e2-cdf1ce04c1c0", + "params" : { + "ql" : [ "select username,name where name='Gladys Kravitz'" ] + }, + "path" : "/users", + "uri" : "http://api.usergrid.com/myorg/myapp/users", + "list" : [ [ "gladys", "Gladys Kravitz" ] ], + "timestamp" : 1374697463190, + "duration" : 25, + "organization" : "myorg", + "applicationName" : "myapp", + "count" : 1 + } + + \ No newline at end of file diff --git a/content/docs/_sources/data-storage/collections.txt b/content/docs/_sources/data-storage/collections.txt new file mode 100644 index 0000000000..fa8652e685 --- /dev/null +++ b/content/docs/_sources/data-storage/collections.txt @@ -0,0 +1,254 @@ +# Collections + +## Creating Collections + +This article describes how to create collections in Advanced Usergrid. All entities are automatically associated with a corresponding collection based on the type property of the entity. You may create empty collections if you wish, but creating an entity of a new type will automatically create a corresponding collection for you. For example, creating a new custom "item" entity, creates an "items" collection. + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Creating a collection + +The following example shows how to create an empty collection. Alternatively, you can create a collection simply by creating a new entity with a 'type' property that corresponds to the collection you wish to create. For more on creating entities, see Creating Custom Data Entities + +### Request Syntax + + curl -X POST https://api.usergrid.com/// + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +collection name Name of the collection to create. + +If the provided value is not a plural word, Usergrid will pluralize it. For example, providing 'item' will create a collection named 'items' but providing 'items' will not create 'itemses'. + +### Example Request/Response + +Request: + + curl -X POST "https://api.usergrid.com/your-org/your-app/item" + +Response: + + { + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ ], + "timestamp" : 1378857079220, + "duration" : 31, + "organization" : "your-org", + "applicationName" : "your-app" + } + +## Retrieving Collections + +This article describes how to retrieve all of the entities in a collection. + +

Note


By default, the Usergrid API returns 10 entities per request. For collections with more than 10 entities, use the returned 'cursor' property to retrieve the next 10 entities in the result set. You may also use the LIMIT parameter in a query string to increase the number of results returned. For more information on using cursors, see [Query Parameters](../data-queries/query-parameters.html).

+ +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Retrieving sets of entities from a collection + +### Request Syntax + + curl -X GET https://api.usergrid.com/// + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +collection Collection UUID or collection name + +### Example Request/Response + +Request: + + curl -X GET "https://api.usergrid.com/your-org/your-app/items" + +Response: + + { + "action" : "get", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "type" : "item", + "name" : "milk", + "created" : 1378405020796, + "modified" : 1378405020796, + "metadata" : { + "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4" + }, + "name" : "milk", + "price" : "3.25" + }, { + "uuid" : "1a9356ba-1682-11e3-a72a-81581bbaf055", + "type" : "item", + "name" : "bread", + "created" : 1378423379867, + "modified" : 1378423379867, + "metadata" : { + "path" : "/items/1a9356ba-1682-11e3-a72a-81581bbaf055" + }, + "name" : "bread", + "price" : "2.50" + } ], + "timestamp" : 1378426821261, + "duration" : 35, + "organization" : "your-org", + "applicationName" : "your-app", + "count" : 2 + } + +## Updating Collections + +This article describes how to perform batch updates on all entities in a collection. Batch updates require the use of a query string in the request, which can either specify all entities in the collection or a subset of entities for the update to be performed on. For more information on queries, see Querying your data. + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Batch updating entities in a collection + +### Request Syntax + + curl -X PUT https://api.usergrid.com////?ql= -d {} + +Note the empty query string (ql=) appended to the URL. + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +collection Collection UUID or collection name property + +An entity property to be updated, formatted as a key-value pair. For example: + + {"property_1":"value_1", "property_2":"value_2",...} + +### Example Request/Response + +Request: + + curl -X PUT https://api.usergrid.com/your-org/your-app/items/?ql= -d '{"availability":"in-stock"}' + +Note the empty ?ql= query string. + +Response: + + { + "action" : "put", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { + "ql" : [ "" ] + }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "31847b9a-1a62-11e3-be04-8d05e96f700d", + "type" : "item", + "name" : "milk", + "price" : "3.25", + "availability" : "in-stock" + "created" : 1378849479113, + "modified" : 1378849567301, + "name" : "milk", + }, { + "uuid" : "3192ac6a-1a62-11e3-a24f-496ca1d42ce7", + "type" : "item", + "name" : "bread", + "price" : "4.00", + "availability" : "in-stock" + "created" : 1378849479206, + "modified" : 1378849567351, + "name" : "bread", + } ], + "timestamp" : 1378849567280, + "duration" : 207, + "organization" : "your-org", + "applicationName" : "your-app" + } + +## Deleting Collections +This article describes how to batch delete entities in a collection. Batch deletes require the use of a query string in the request, which specifies a subset of entities to be deleted. For more information on queries, see Querying your data. + +Currently, collections cannot be deleted; however, you can delete all of the entities from a collection. + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Batch deleting entities in a collection + +### Request Syntax + + curl -X DELETE https://api.usergrid.com////?ql= + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +collection Collection UUID or collection name +query A query string that specifies the subset of entities to delete + +(for more information on queries, see Querying your data) + +### Example Request/Response + +The following example will delete the first 5 entities in a collection. + +Request: + + curl -X DELETE https://api.usergrid.com/your-org/your-app/items/?ql="limit=5" + +Response: + + { + "action" : "delete", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { + "ql" : [ "" ] + }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "53fe3700-0abe-11e3-b1f7-1bd100b8059e", + "type" : "item", + "name" : "milk", + "price" : "3.25", + "created" : 1377129832047, + "modified" : 1377129832047, + "metadata" : { + "path" : "/items/53fe3700-0abe-11e3-b1f7-1bd100b8059e" + }, + "name" : "milk" + }, { + "uuid" : "5ae1fa7a-0abe-11e3-89ab-6be0003c809b", + "type" : "item", + "name" : "bread", + "price" : "4.00", + "created" : 1377129843607, + "modified" : 1377129843607, + "metadata" : { + "path" : "/items/5ae1fa7a-0abe-11e3-89ab-6be0003c809b" + }, + "name" : "bread" + } ], + "timestamp" : 1378848117272, + "duration" : 12275, + "organization" : "your-org", + "applicationName" : "your-app" + } + + \ No newline at end of file diff --git a/content/docs/_sources/data-storage/data-store-dbms.txt b/content/docs/_sources/data-storage/data-store-dbms.txt new file mode 100644 index 0000000000..56fbbdb931 --- /dev/null +++ b/content/docs/_sources/data-storage/data-store-dbms.txt @@ -0,0 +1,109 @@ +# The Usergrid Data Store + +The Usergrid data store is backed by Cassandra, an open source distributed DBMS. Cassandra isn’t a relational database system (RDBMS), and is sometimes placed in the category of “NoSQL” or “schema-less” databases. + + +

Note

+Usergrid is not a relational database. Optimizing for performance on a non-relational database like Cassandra differs a bit from relational databases. For more information, see [Optimizing access to your Usergrid data store](../data-storage/optimizing-access.html).

+ + +Cassandra is specifically designed to support applications that need flexibility and high scalability, particularly web and mobile applications. Usergrid client applications write and read data formatted as JavaScript Object Notation (JSON). (Usergrid provides SDKs through which client apps can do much of this work in their native language. For more information, see [Usergrid SDKs](../sdks/tbd.html).) + +With Cassandra as the underlying DBMS, apps benefit from: + +Fast writes to the data store. +* A distributed architecture that means no single point of failure. +* Flexibility in data model design. You aren't constrained by a schema. +* Linear scalability. + +If you have experience with relational databases and are unfamiliar with "NoSQL" databases, the following table might be a helpful start. It maps the high-level concepts of an RDBMS’s data model both to Cassandra’s and to the Usergrid, which is backed by Cassandra. + + + + + + + + + + + + + + + + + + + + + + + + + + +
RDBMSCassandraUsergrid
Each tuple is modeled asA row.A row.An entity. Written and retrieved as JSON, an entity contains values for all of its properties in the way a row has values for columns.
Each data attribute is modeled asA column.A column. Many thousands of columns are supported.A entity property. An entity has a default set of properties, including the entity’s UUID. You can add many more to support your application.
Each group of attributes is modeled asA table.A column family. Unlike rows in tables, rows in a column family can have differing numbers of columns. Because you’re not using a schema to define the model, you can update the column list for a row at any time.An entity collection. As with its underlying Cassandra column family, a collection can have entities with differing numbers of properties. In other words, just because one entity has an authorId property doesn’t mean that other entities in its collection need to.
+ +The following examples from a product database provide simple illustrations of these differences. + +An RDBMS table has a schema-defined set of columns per row. + +.. image:: rdbms.png + +A Cassandra column family includes rows that can have differing column sets. + +.. image:: cassandra.png + +In the JSON from the Usergrid application, the products are represented as entities. Note that each entity in the entities array below has a slightly different set of properties, like the columns in a Cassandra column family. + + { + "action" : "get", + "application" : "", + "params" : {}, + "path" : "/products", + "uri" : "https://api.usergrid.com/my_org/my_app/products", + "entities" : [ { + "uuid" : "", + "type" : "product", + "created" : 1395410098517, + "modified" : 1395410098517, + "image" : "http://path.jpg", + "metadata" : { + "path" : "/products/" + }, + "name" : "Bouncy Castle", + "sku" : "35450349822" + }, + { + "uuid" : "", + "type" : "product", + "created" : 1395409669686, + "modified" : 1395409669686, + "image" : "http://path.jpg", + "metadata" : { + "path" : "/products/" + }, + "description" : "It makes coffee.", + "name" : "Coffee Maker", + "sku" : "60723023589" + }, + { + "uuid" : "", + "type" : "product", + "created" : 1395407700578, + "modified" : 1395407700578, + "metadata" : { + "path" : "/products/" + }, + "name" : "Air Mattress", + "sku" : "53045985365" + }], + "timestamp" : 1396290037640, + "duration" : 91, + "organization" : "my_org", + "applicationName" : "my_app", + "count" : 3 + } + + \ No newline at end of file diff --git a/content/docs/_sources/data-storage/entities.txt b/content/docs/_sources/data-storage/entities.txt new file mode 100644 index 0000000000..be77ebd29b --- /dev/null +++ b/content/docs/_sources/data-storage/entities.txt @@ -0,0 +1,512 @@ +# Entities + +## Creating Custom Data Entities +This article describes how to create custom data entities and entity properties. Entity types correspond to the name of collection to which they are posted. For example, if you create a new custom "dog" entity, a "dogs" collection will be created if one did not already exist. If a "dogs" collection already exists, the new "dog" entity will be saved in it. All user-defined properties are indexed, and strings that contain multiple words are keyword-indexed. + +The methods cited in this article should be used to create custom data entities. If you are using one of the Usergrid SDKs, use one of the entity type-specific SDK methods to create default data entities. + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Creating a custom entity +When a new entity is created, Usergrid will automatically create a corresponding collection if one does not already exist. The collection will automatically be named with the plural form of the entity type. For example, creating a custom entity of type 'item' will automatically create a collection named 'items' in which all future 'item' entities will be saved. + +### Request Syntax + + curl -X POST https://api.usergrid.com/// -d 'json_object' + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +entity_type Entity type to create. +json_object JSON representation of entity properties + +(For a full list of default properties, see Default Data Entity Types) + +Usergrid will create a corresponding collection if one does not already exist. To add an entity to an existing collections, use the pluralized collection name for entity_type. + +### Example Request/Response + +Request: + + curl -X POST "https://api.usergrid.com/your-org/your-app/item" -d '{"name":"milk", "price":"3.25"}' + +Response: + + { + "action" : "post", + "application" : "4a1edb70-d7a8-11e2-9ce3-f315e5aa568a", + "params" : { }, + "path" : "/items", "uri" : "http://api.usergrid.com/my-org/my-app/items", + "entities" : [ { + "uuid" : "83e9b7ea-e8f5-11e2-84df-e94123890c7a", + "type" : "item", + "name" : "milk", + "created" : 1373415195230, + "modified" : 1373415195230, + "metadata" : { + + "path" : "/items/83e9b7ea-e8f5-11e2-84df-e94123890c7a" + }, + "name" : "milk", + "price" : "3.25" + } ], + "timestamp" : 1373415195225, + "duration" : 635, + "organization" : "my-org", + "applicationName" : "my-app" + } + +## Creating multiple custom entities + +### Request Syntax + + curl -X POST https://api.usergrid.com//// -d 'json_array' + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or name +app Application UUID or name +entity_type Custom entity type to create. +json_array JSON array of entities to be created. + +Usergrid will create a corresponding collection if one does not already exist. To add an entity to an existing collections, use the collection name or collection UUID in place of the entity type. + +### Example Request/Response + +Request: + + curl -X POST "https://api.usergrid.com/your-org/your-app/item" -d '[{"name":"milk", "price":"3.25"}, {"name":"bread", "price":"2.50"}]' + +Response: + + { + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e9sjwsf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "f3a8061a-ef0b-11e2-9e92-5f4a65c16193", + "type" : "item", + "name" : "milk", + "price" : "3.25", + "created" : 1374084538609, + "modified" : 1374084538609, + "metadata" : { + "path" : "/multis/f3a8061a-ef0b-11e2-9e92-5f4a65c16193" + }, + "name" : "milk" + }, { + "uuid" : "f3be262a-ef0b-11e2-a51b-6715d5ef47a6", + "type" : "item", + "name" : "bread", + "price" : "2.50", + "created" : 1374084538754, + "modified" : 1374084538754, + "metadata" : { + "path" : "/items/f3be262a-ef0b-11e2-a51b-6715d5ef47a6" + }, + "name" : "bread" + } ], + "timestamp" : 1374084538584, + "duration" : 388, + "organization" : "your-org", + "applicationName" : "your-app" + } + +### Creating an entity with sub-properties + +Any valid JSON object can be stored in an entity, regardless of the level of complexity, including sub-properties. For example, suppose you have an 'items' collection that contains an entity named 'milk'. You might store the different varieties of milk as sub-properties of a 'varieties' property: + + { + "type" : "item" + "name" : "milk" + "varieties" : [ { + "name" : "1%", + "price" : "3.25", + "sku" : "0393847575533445" + }, { + "name" : "whole", + "price" : "3.85", + "sku" : "0393394956788445" + }, { + "name" : "skim", + "price" : "4.00", + "sku" : "0390299933488445" + } ] + } + +### Updating sub-properties + +An array of sub-properties is treated as a single object. This means that sub-properties cannot be updated atomically. All sub-properties of a given property must be updated as a set. +For more on updating an existing sub-property, see [Updating Data Entities](../data-storage/entities.html#updating-data-entities). + +Example Request/Response + + Request: + //Note the use of square brackets for specifying multiple nested objects + curl -X POST "https://api.usergrid.com/your-org/your-app/items" -d '{"varieties":[{"name":"1%","price" : "3.25", "sku" : "0393847575533445"},{"name" : "whole", "price" : "3.85", "sku" : "0393394956788445"}, {"name" : "skim", "price" : "4.00", "sku" : "0390299933488445"}]}' + Response: + { + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "0d7cf92a-effb-11e2-917d-c5e707256e71", + "type" : "item", + "name" : "milk", + "created" : 1374187231666, + "modified" : 1374187231666, + "metadata" : { + "path" : "/items/0d7cf92a-effb-11e2-917d-c5e707256e71" + }, + "name" : "milk", + "varieties" : [ { + "name" : "1%", + "price" : "3.25", + "SKU" : "0393847575533445" + }, { + "name" : "whole", + "price" : "3.85", + "SKU" : "0393394956788445" + }, { + "name" : "skim", + "price" : "4.00", + "SKU" : "0390299933488445" + } ] + } ], + "timestamp" : 1374187450826, + "duration" : 50, + "organization" : "your-org", + "applicationName" : "your-app" + } + +.. ----------------------------------------------------------------------------- + +## Retrieving Data Entities +This article describes how to retrieve entities from your account. + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +With the exception of the user entity, all data entities can be retrieved by using their UUID or a 'name' property. The user entity can be retrieved by UUID or the 'username' property. The value for the 'name' or 'username' property must be unique. + +### Retrieving an entity + +### Request Syntax + + curl -X GET https://api.usergrid.com//// + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +collection Collection UUID or collection name +entity Entity UUID or entity name + +### Example Request/Response + +Request: + +Retrieve by UUID: + + curl -X GET "https://api.usergrid.com/your-org/your-app/items/da4a50dc-38dc-11e2-b2e4-02e81adcf3d0" + +Retrieve by 'name' property: + + curl -X GET "https://api.usergrid.com/your-org/your-app/items/milk" + +Response: + + { + "action" : "get", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/amuramoto/sandbox/items", + "entities" : [ { + "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "type" : "item", + "name" : "milk", + "created" : 1378405020796, + "modified" : 1378405020796, + "metadata" : { + "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4" + }, + "name" : "milk", + "price" : "3.25" + } ], + "timestamp" : 1378405025763, + "duration" : 31, + "organization" : "amuramoto", + "applicationName" : "sandbox" + } + +### Retrieving multiple entities + +This example describes how to retrieve multiple entities by UUID. You can also retrieve a set of entities by using a query string. For more information on querying your data, see Querying your data. + +### Request Syntax + + curl -X GET https://api.usergrid.com///?ql= uuid = OR uuid = ; ... + +Parameters + +Parameter Description +--------- ----------- +org_id Organization UUID or organization name +app_id Application UUID or application name +collection Collection UUID or collection name +query A url-encoded query string of entity properties to be matched. + +The query must be in Usergrid Query Language, for example: + + ?ql=uuid=""" OR name="" OR... + +You may also specify the following for certain entity types: + +User entities: username = + +All other entities except groups: name = + +### Example Request/Response + +Request: + + //note the url-encoded query string + curl -X GET "https://api.usergrid.com/your-org/your-app/items?ql=name%3D'milk'%20OR%20UUID%3D1a9356ba-1682-11e3-a72a-81581bbaf055&limit=" + +Note: The query parameter of the request must be url encoded for curl requests + +Response: + + { + "action" : "get", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { + "ql" : [ "name='milk' OR UUID=1a9356ba-1682-11e3-a72a-81581bbaf055" ] + }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "type" : "item", + "name" : "milk", + "created" : 1378405020796, + "modified" : 1378405020796, + "metadata" : { + "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4" + }, + "name" : "milk", + "price" : "3.25" + }, { + "uuid" : "1a9356ba-1682-11e3-a72a-81581bbaf055", + "type" : "item", + "name" : "bread", + "created" : 1378423379867, + "modified" : 1378423379867, + "metadata" : { + "path" : "/items/1a9356ba-1682-11e3-a72a-81581bbaf055" + }, + "name" : "bread", + "price" : "2.50" + } ], + "timestamp" : 1378423793729, + "duration" : 63, + "organization" : "your-org", + "applicationName" : "your-app", + "count" : 2 + } + + +.. -------------------------------------------------------------------------------- + +## Updating Data Entities + +This article describes how to update entities in your account. + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Updating an entity +One or more properties can be updated with a single PUT request. For information on updating sub-properties, see Updating sub-properties below. + +### Request Syntax + + curl -X PUT https://api.usergrid.com//// -d {} + +Parameters + +Parameter Description +--------- ----------- +org_id Organization UUID or organization name +app_id Application UUID or application name +collection Name of the collection containing the entity to be updated +uuid|name UUID or name of the data entity to be updated +json_object JSON object with a field for each property to be updated + +An entity property to be updated, formatted as a key-value pair. For example: + + {"property_1":"value_1", "property_2":"value_2",...} + +### Example Request/Response + +Request: + + curl -X PUT https://api.usergrid.com/your-org/your-app/items/milk -d '{"price":"4.00", "availability":"in-stock"}' + +Response: + + { + "action" : "put", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "type" : "item", + "name" : "milk", + "created" : 1378405020796, + "modified" : 1378505705077, + "availability" : "in-stock", + "metadata" : { + "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4" + }, + "name" : "milk", + "price" : "4.00" + } ], + "timestamp" : 1378505705050, + "duration" : 87, + "organization" : "your-org", + "applicationName" : "your-app" + } + + +### Updating a sub-property + +Data entities may contain sets of sub-properties as nested JSON objects. Unlike normal entity properties, however, sub-properties cannot be updated individually. Updating a nested object will cause all sub-properties within it to be overwritten. + +For example, if you have a data entity with the following nested object: + +### Request Syntax + + curl -X PUT https://api.usergrid.com//// -d '{ : [{}, {}...]}' + +Parameters + +Parameter Description +--------- ----------- +org_id Organization UUID or organization name +app_id Application UUID or application name +collection Name of the collection containing the entity to be updated +uuid|name UUID or name of the data entity to be updated +json_object JSON object with a field for each property to be updated + +### Example Request/Response + +Request: + + curl -X PUT https://api.usergrid.com/your-org/your-app/items/milk -d '{"varieties":[{"name":"1%","price":"3.25"},{"name":"whole","price":"4.00"}]}' + +Response: + + { + "action" : "put", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "type" : "item", + "name" : "milk", + "created" : 1378405020796, + "modified" : 1378761459069, + "availability" : "in-stock", + "metadata" : { + "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4" + }, + "name" : "milk", + "uri" : "http://api.usergrid.com/your-org/your-app/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "varieties" : [ { + "name" : "1%", + "price" : "3.25" + }, { + "name" : "whole", + "price" : "4.00" + } ] + } ], + "timestamp" : 1378761459047, + "duration" : 62, + "organization" : "your-org", + "applicationName" : "your-app" + } + +## Deleting Data Entities + +This article describes how to delete data entities. + +__Note__:Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Deleting an entity + +### Request Syntax + + curl -X DELETE https://api.usergrid.com//// + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +collection Collection UUID or collection name +entity Entity UUID or entity name + +### Example Request/Response + +Request: + +Delete by UUID: + + curl -X DELETE "https://api.usergrid.com/your-org/your-app/items/da4a50dc-38dc-11e2-b2e4-02e81adcf3d0" + +Delete by 'name' property: + + curl -X DELETE "https://api.usergrid.com/your-org/your-app/items/milk" + +Response: + + { + "action" : "delete", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "328fe64a-19a0-11e3-8a2a-ebc6f49d1fc4", + "type" : "item", + "name" : "milk", + "created" : 1378766158500, + "modified" : 1378766158500, + "metadata" : { + "path" : "/items/328fe64a-19a0-11e3-8a2a-ebc6f49d1fc4" + }, + "name" : "milk", + "price" : "3.25" + } ], + "timestamp" : 1378766172016, + "duration" : 324, + "organization" : "your-org", + "applicationName" : "your-app" + } + + \ No newline at end of file diff --git a/content/docs/_sources/data-storage/optimizing-access.txt b/content/docs/_sources/data-storage/optimizing-access.txt new file mode 100644 index 0000000000..2e5c0b6088 --- /dev/null +++ b/content/docs/_sources/data-storage/optimizing-access.txt @@ -0,0 +1,185 @@ +# Data Store Best Practices +The Usergrid data store is backed by Cassandra, an open source distributed DBMS. Cassandra is specifically designed to support applications that need flexibility and high scalability, particularly web and mobile applications. To get the most out of your Usergrid application, you should optimize your data access with this kind of database in mind. + +## Put your data in as you'll want to get it out +The best practices described here are all related to the theme of putting your data in the way you’ll want to get it out. You’ll model your data with your likely read requests in mind rather than by modeling around the structure of the data itself (as you might with a relational database). In many cases, you can avoid using queries that are inefficient for this kind of database. + +You can use the following techniques to optimize data store access: + +* __Denormalize and duplicate__. By creating a data model that strategically denormalizes and duplicates data, you can avoid costly queries. In other words, you model the data so that all of the data for a given request is all in one place rather than scattered in a way that a query must account for. + +* __Create direct paths to the data you’ll want__. You can optimize your app’s performance by connecting entities your code retrieves most often. With connections, you can avoid some queries that might add complexity and reduce performance. + +## Best practice: Denormalize for pre-computed query results +If you’re familiar with designing relational databases, you’re probably used to normalizing the structure of your data as much as possible. When normalizing an RDBMS data model, you minimize redundancy by ensuring that a column from one table is duplicated only once in any other table, and only when necessary to create primary/secondary key relationships. You then retrieve data that spans tables by joining them with an SQL query. + +In contrast, with the Usergrid data store you’ll get better performance by strategically denormalizing and duplicating data. When you denormalize, you combine data from what might (in a relational model) have been separate tables. When duplicating, you intentionally maintain copies of certain entity properties across multiple entities. By denormalizing and duplicating, you can collect the results of requests into a single entity rather than relying on a query. + +Part of designing your data model should include identifying the queries your client will make. Then in your data model design, you capture the results of those queries in advance by writing that data into entities of one collection you can read from later. + +### Getting review data the relational way +For example, take a closer look at the relational case through a product database. Imagine you want to present a list of all reviews for a product. When a user chooses a review from the list, you’ll show them a view that includes the review’s title, body, and rating; the product it describes; and who wrote the review. That way, your user will be able to click through to more information about the product or reviewing user. + +In a relational database, you’d likely have separate tables for the review-specific information and a rating; for the product; and for the user. Your reviews table would include secondary keys with which to join reviews to the users and products tables. Maybe something like this: + +.. image:: reviews.png + +To get the data you need, your query might look like the SQL query below. By getting UUIDs for the user and product into your client code, you’re able to give the user a way to get user and product information from the review. + + SELECT review.title, review.body, review.rating, review.uuid, + user.name, user.uuid, product.name, product.uuid + FROM reviews + INNER JOIN users + ON users.uuid = reviews.authorId + INNER JOIN products + ON products.uuid = reviews.productId + WHERE reviews.uuid = + +But due to Cassandra’s distributed, high-scale design, a join such as this wouldn’t work. So in the Usergrid, you’d get the data by first storing it all in one place. + +### Using a denormalized model to store (then retrieve) data +In the Usergrid, a more efficient way to get the same result would start by including related user and product data with the review data. This would give you a single place to get all the data you'll show. + +The following shows how that model might look as entities in the Usergrid. (The users and products entities are included here to remind you that they exist, but they aren’t actually used in this denormalization example.) + +.. image:: reviews2.png + +This use case assumes that your user and product data are already in the data store. In the following API request code, you’re just adding a new review written by a user about a particular product. The JSON body is your new review entity (the JSON here is non-entitized to make it readable). + + POST https://api.usergrid.com/my_org/my_app/reviews -d { + "title" : "Tempted to climb in myself.", + "body" : "I mean, who doesn't love a bouncy castle? The kids love it!", + "rating" : 3, + "authorName" : "Jennie", + "authorUUID" : , + "authorImage" : "http://.png", + "productUUID" : , + "productImage" : "http://.jpg", + "productName" : "Magic Castle Bounce House Inflatable Bouncer" + } + +Notice that you’re adding user and product data (which your client code would have at hand when the user posts the review) when you’re adding the review-specific data. + +Retrieving all the data from one place +You’d get the review, including the subset of product and user data you need right away, by making one API call such as the following (note there’s no SQL-like query string needed): + + GET http://api.usergrid.com/my_org/my_app/reviews/ + +Your result might look like this. The highlighted lines show data you'd present to the user. + + { + "action" : "get", + "application" : "", + "params" : { }, + "path" : "/reviews", + "uri" : "https://api.usergrid.com/my_org/my_app/reviews", + "entities" : [ { + "uuid" : "", + "type" : "review", + "created" : 1395410364673, + "modified" : 1395410364673, + "authorName" : "Jennie", + "authorImage" : ".png", + "authorUUID" : "", + "body" : "I mean, who doesn't love a bouncy castle? The kids love it!", + "metadata" : { + "path" : "/reviews/" + }, + "productImage" : "http://.jpg", + "productName" : "Magic Castle Bounce House Inflatable Bouncer", + "productUUID" : "", + "rating" : 3, + "title" : "Tempted to climb in myself." + } ], + "timestamp" : 1395764951934, + "duration" : 16, + "organization" : "my_org", + "applicationName" : "my_app" + } + +This gives you, in one request, all the review information you’d planned on presenting to your app’s users for a single view. Your client code could retrieve the review entity in the result, along with the product and user data, then present it all as a review. + +Best practice: Connect entities to simplify scoped requests +Another way to streamline your requests is to connect entities by using the built-in connections feature. In a sense, a connection can replace the WHERE clause of a query you might have written. + +Getting back to the review example, imagine you want to retrieve all of the reviews written by a particular user. In the relational example, you might have an SQL query such as this: + + SELECT * FROM reviews WHERE authorId = ; + +Even in the Usergrid, you could use a similar syntax in a query string appended to an API path. Working from the review entity model in the preceding example, that might look like this (though yours would likely entitize the spaces): + + GET http://api.usergrid.com/my_org/my_app/reviews?ql=select * where + authorUUID= + +But if this is an API call you’re going to be making often, there’s a better way. Instead, create a connection between the review and the user when your code creates the review. You can connect entities with a verb that describes their relationship to one another. + +The following creates Jennie’s review and at the same time connects her as the person who “wrote” it. (For easier reading, this example contains spaces you wouldn’t be able to include.) + + POST http://api.usergrid.com/my_org/my_app/users/jennie/wrote/reviews { + "title" : "Tempted to climb in myself.", + "body" : "I mean, who doesn't love a bouncy castle? The kids love it!", + "rating" : 3, + "authorName" : "Jennie", + "authorImage" : "http://.png", + "productName" : "Magic Castle Bounce House Inflatable Bouncer", + "productImage" : "http://.jpg" + } + +When reading the data, you’d retrieve all of the reviews Jennie has written with a URL that’s nearly identical, minus the JSON: + + GET http://api.usergrid.com/my_org/my_app/users/jennie/wrote/reviews + +Your request result would look something like the following. Here, the entities array returned contains the reviews you connected with Jennie (though there’s only one in this example). The connection-specific metadata is highlighted. + + { + "action" : "get", + "application" : "", + "params" : { }, + "path" : "/users//wrote", + "uri" : "https://api.usergrid.com/my_org/my_app/users//wrote", + "entities" : [ { + "uuid" : "", + "type" : "review", + "created" : 1395410364673, + "modified" : 1395410364673, + "authorName" : "Jennie", + "authorImage" : "http://.png", + "authorUUID" : "", + "body" : "I mean, who doesn't love a bouncy castle? Kids love it!", + "metadata" : { + "connecting" : { + "wrote" : "/users//wrote//connecting/wrote" + }, + "path" : "/users//wrote/", + }, + "productImage" : "http://.jpg", + "productName" : "Magic Castle Bounce House Inflatable Bouncer", + "productUUID" : "", + "rating" : 3, + "title" : "Tempted to climb in myself." + } ], + "timestamp" : 1395777037697, + "duration" : 19, + "organization" : "my_org", + "applicationName" : "my_app" + } + +To retrieve a particular review written by Jennie, you could use something like the following: + + GET http://api.usergrid.com/my_org/my_app/users/jennie/wrote/reviews/ + +You can create connections to set up relationships you can use to later retrieve data quickly and with a simple syntax. + +For example, when creating a connected entity (such as the review entity here), you can at the same time create other connections to connect the product to the new review, then connect the product to its reviewer (paths are abbreviated in these examples): + + POST /users/jennie/wrote/reviews {} + POST /products//reviewedIn/reviews/ + POST /products//reviewedBy/users/jennie + +Having created these connections for each review you post, in addition to getting the review the user wrote, you could later also: + +Get the reviews for a product: + + GET /products//reviewedIn/reviews + Get the users who reviewed the product: + GET /products//reviewedBy/users diff --git a/content/docs/_sources/entity-connections/connecting-entities.txt b/content/docs/_sources/entity-connections/connecting-entities.txt new file mode 100644 index 0000000000..1c6219e83b --- /dev/null +++ b/content/docs/_sources/entity-connections/connecting-entities.txt @@ -0,0 +1,60 @@ +# Connecting entities + +When creating a connection, if you specify the collection of the entity being connected to, you can create the connection using the value of its 'name' property or its UUID. + +## Request syntax + +To create a connection, the entity being connected to can either be specified by just its UUID, or both its collection and the value of its 'name' property. + +Connect by UUID + + curl -X POST https://api.usergrid.com////// + +Connect by 'name' property + + curl -X POST https://api.usergrid.com/////// + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +connecting_collection Name or UUID of the collection of the connecting entity. +connecting_entity Name or UUID of the connecting entity. +relationship Type of connection being created (e.g., likes) +connected_collection Name or UUID of the collection of the entity being connected to. +connected_entity Name or UUID of the entity being connected to. + +If the connecting entity is a 'user' entity, the 'username' should be used rather than the 'name'. + +'connected_collection' is not required if the entity being connected to is specified by its UUID. + +Example request + + curl -X POST http://api.usergrid.com/your-org/your-app/users/Arthur/likes/6c56ffda-9e75-11e3-99fd-8dd1801e534c + +Example Response + + { + "action" : "post", + "application" : "db1e60a0-417f-11e3-9586-0f1ff3650d20", + "params" : { }, + "path" : "/users/174785aa-8ea8-11e3-ae1f-eb20e5bce407/likes", + "uri" : "https://api.usergrid.com/my-org/my-app/users/174785aa-8ea8-11e3-ae1f-eb20e5bce407/likes", + "entities" : [ { + "uuid" : "6c56ffda-9e75-11e3-99fd-8dd1801e534c", + "type" : "user", + "name" : "Arthur", + "created" : 1393371291725, + "modified" : 1393371291725, + "metadata" : { + "path" : "/users/174785aa-8ea8-11e3-ae1f-eb20e5bce407/likes/6c56ffda-9e75-11e3-99fd-8dd1801e534c" + } + } ], + "timestamp" : 1393371455487, + "duration" : 77, + "organization" : "your-org", + "applicationName" : "your-app" + } + \ No newline at end of file diff --git a/content/docs/_sources/entity-connections/disconnecting-entities.txt b/content/docs/_sources/entity-connections/disconnecting-entities.txt new file mode 100644 index 0000000000..b52d62dcc6 --- /dev/null +++ b/content/docs/_sources/entity-connections/disconnecting-entities.txt @@ -0,0 +1,79 @@ +# Disconnecting entities + +To disconnect a user from other data, perform a DELETE operation against the same endpoint at which you posted to create the connection. + +## Request syntax + +Disconnect by UUID + + curl -X DELETE https://api.usergrid.com////// + +Disconnect by 'name' property + + curl -X DELETE https://api.usergrid.com/////// + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +connecting_collection Name or UUID of the collection of the connecting entity. +connecting_entity Name or UUID of the connecting entity. +relationship Type of connection being created (e.g., likes) +connected_collection Name or UUID of the collection of the entity being connected to. +connected_entity Name or UUID of the entity being connected to. + +If the connecting entity is a 'user' entity, the 'username' should be used rather than the 'name'. + +'connected_collection' is not required if the entity being connected to is specified by its UUID.Parameter + +Example request + + curl -X DELETE https://api.usergrid.com/your-org/your-app/users/Arthur/likes/users/Ford + +Example response + + { + "action" : "delete", + "application" : "k88dh4f-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes", + "uri" : "https://api.usergrid.com/your-org/your-app/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes", + "entities" : [ { + "uuid" : "5bcc47ca-cfed-11e3-8bde-a7e008061e10", + "type" : "user", + "created" : 1398810410556, + "modified" : 1398810410556, + "username" : "Ford", + "activated" : true, + "metadata" : { + "connecting" : { + "likes" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/connecting/likes" + }, + "path" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10", + "sets" : { + "rolenames" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/roles", + "permissions" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/permissions" + }, + "connections" : { + "friends" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/friends", + "likes" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/likes" + }, + "collections" : { + "activities" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/activities", + "devices" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/devices", + "feed" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/feed", + "groups" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/groups", + "roles" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/roles", + "following" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/following", + "followers" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/followers" + } + } + } ], + "timestamp" : 1398962837195, + "duration" : 85, + "organization" : "your-org", + "applicationName" : "your-app" + } + \ No newline at end of file diff --git a/content/docs/_sources/entity-connections/relationships.txt b/content/docs/_sources/entity-connections/relationships.txt new file mode 100644 index 0000000000..73bc6c365e --- /dev/null +++ b/content/docs/_sources/entity-connections/relationships.txt @@ -0,0 +1,98 @@ +# Relationships + +## Creating connections between entities + +One of the most useful features of Usergrid is the ability to create +connections between entities. A simple example of this is the +Twitter-like use of *following*, where one user forms a connection with +another by subscribing to any tweets they post. [Messagee +Example](/messagee-example) walks you through an example of following +other users in our sample app, *Messagee*. Here is the basic format: + + POST https://api.usergrid.com/my-org/my-app/users/fred/following/users/barney + +This API call results in two users, Fred and Barney, linked with a +connection where Fred is following Barney. + +If you create a *following* connection between two users, Apache Usergrid +automatically creates a virtual connection called *followers* that +mirrors the *following* connection. In other words, if you create a +connection where Fred is following Barney, Apache Usergrid automatically +creates a virtual connection where Fred is a follower of Barney. + +Note that there is no mirror connection established. Apache Usergrid only +creates a mirror connection when you create a *following* connection. It +does not create a mirror connection for other verbs such as likes. + +You can see all the users that Fred is following, in this case only +Barney, by making the following API call: + + GET https://api.usergrid.com/my-org/my-app/users/fred/following + +You can see all of barney’s followers, in this case only Fred, by making +the following API call: + + GET https://api.usergrid.com/my-org/my-app/users/barney/followers + +The *followers* connection is a virtual connection because you can’t use +it to link two entities. In other words, you can’t make fred a follower +of barney by using a *followers* connection.  **This is wrong:** + + POST https://api.usergrid.com/my-org/my-app/users/barney/followers/users/fred + +To create a *following* connection with the users switched, so that +Barney is following Fred, do this: + + POST https://api.usergrid.com/my-org/my-app/users/barney/following/users/fred + +You can now see Fred’s followers (only Barney) by making the following +call: + + GET https://api.usergrid.com/my-org/my-app/users/fred/followers + +## Creating other connections + +You can extend this connection structure to create connections using any +"verb" that can link two entities. For example, you could use likes to +denote a connection between a user and his dog. First, create a dogs +collection: + + POST https://api.usergrid.com/my-org/my-app/dogs + +Then populate this collection with a new dog named Dino: + + POST https://api.usergrid.com/my-org/my-app/dogs {"name" : "dino"} + +Then create a likes connection between Fred and his dog Dino: + + POST https://api.usergrid.com/my-org/my-app/users/fred/likes/dogs/dino + +Getting connections +------------------- + +### Get all connections for an entity + +To get a list that only contains the connections, do a GET on the +connections sub-property of the entity: + + GET https://api.usergrid.com/my-org/my-app/users/fred/connections + +### Get information on a specific connection type + +To get a list of users who like Fred: + + GET https://api.usergrid.com/my-org/my-app/users/fred/connecting/likes + +To get a list of all dogs that Fred likes: + + GET https://api.usergrid.com/my-org/my-app/users/fred/likes/dog + +Deleting a connection +--------------------- + +You can delete a connection in a way similar to creating one. Just +replace the POST method with the DELETE method. For example, you can +delete the connection between fred and barney with the following API +call: + + DELETE https://api.usergrid.com/my-org/my-app/users/fred/following/barney diff --git a/content/docs/_sources/entity-connections/retrieving-entities.txt b/content/docs/_sources/entity-connections/retrieving-entities.txt new file mode 100644 index 0000000000..6da8577f67 --- /dev/null +++ b/content/docs/_sources/entity-connections/retrieving-entities.txt @@ -0,0 +1,93 @@ +# Retrieving connections + +To see all of the connection types associated with an entity, simply retrieve the entity. + +All of the connection types the entity has made to other entities will appear in the ``metadata.connections`` property. + +All of the connection types that other entities have made to the entity will appear in the ``metadata.connecting`` property. + +For user entities, following/followers connections can be accessed by sending a ``GET`` request to the URL in the ``collections.following`` and ``collections.follower``s properties. + +Retrieve connected entities by connection type +To get a list of entities a specified entity has connected to with a specific connection type, do the following: + +## Request syntax + + curl -X GET https://api.usergrid.com///// + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +collection Name or UUID of the collection of the entity you want to retrieve the connections of. +entity Name or UUID of the entity whose connections you want to retrieve +relationship The connection type you want to retrieve the entities for. + +For example, specifying a relationship of 'likes' would return a list of all entities that have the 'likes' connection with the specified entity. + +Example request + + curl -X GET https://api.usergrid.com/your-org/your-app/users/Arthur/likes + +Example response + +Notice that the entities are returned as a JSON array in the entities property. + + { + "action" : "get", + "application" : "dk88fh4r-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes", + "uri" : "https://api.usergrid.com/your-org/your-app/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes", + "entities" : [ { + "uuid" : "5bcc47ca-cfed-11e3-8bde-a7e008061e10", + "type" : "user", + "created" : 1398810410556, + "modified" : 1398810410556, + "username" : "Ford", + "activated" : true, + "metadata" : { + "connecting" : { + "likes" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/connecting/likes" + }, + "path" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10", + "sets" : { + "rolenames" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/roles", + "permissions" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/permissions" + }, + "collections" : { + "activities" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/activities", + "devices" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/devices", + "feed" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/feed", + "groups" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/groups", + "roles" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/roles", + "following" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/following", + "followers" : "/users/58606d0a-cfed-11e3-a694-dbf5228024a7/likes/5bcc47ca-cfed-11e3-8bde-a7e008061e10/followers" + } + } + } ], + "timestamp" : 1398884631067, + "duration" : 41, + "organization" : "your-org", + "applicationName" : "your-app" + } + +## Retrieve all connected entities + +To get a list of all the entities a specified entity has connected to, use the same method as shown above in Retrieve connected entities by connection type, and set the relationship to connections. + +All of the entities that have made a connection of that type to the specified entity will be returned in the entities property of the response. + +## Retrieve all connecting entities by type + +To get a list of all the entities that have created a connection of a specific type to a specified entity, use the same method as shown above in Retrieve connected entities by connection type, and set the relationship to ``connecting/``. + +All of the entities that have made a connection to the specified entity will be returned in the entities property of the response. + +## Retrieve all connecting entities + +To get a list of all the entities that have connected to a specified entity, use the same method as shown above in Retrieve connected entities by connection type, and set the relationship to connecting. + +All of the entities that have made a connection to the specified entity will be returned in the entities property of the response. \ No newline at end of file diff --git a/content/docs/_sources/geolocation/geolocation.txt b/content/docs/_sources/geolocation/geolocation.txt new file mode 100644 index 0000000000..3da555cefb --- /dev/null +++ b/content/docs/_sources/geolocation/geolocation.txt @@ -0,0 +1,72 @@ +# Geolocating your Entities +Many of today's apps are enhanced by the use of geolocation – wireless detection of the physical location of a remote device. These apps determine the user's position and use this data to enhance user experience. For example, apps can capture the exact location where a picture was taken or determine what businesses stored in the database to return to the user based on their current location. + +API Services provides a standard format for storing geolocation information in any entity, as well as syntax for querying that data based on distance from a latitude/longitude point. + +## Saving location data in an entity +In API Services, geolocation data is saved in the location property of an entity with latitude and longitude sub-properites in the following format: + + "location": { + "latitude": , + "longitude": + } + +An entity's geolocation can be specified when the entity is [created](../data-storage/entities.html#creating-custom-data-entities) or added later by [updating](../data-storage/entities.html#updating-data-entities) an existing entity. + +For example, the following entity describes a restaurant: + + { + "uuid" : "03ae956a-249f-11e3-9f80-d16344f5a0e1", + "type" : "restaurant", + "name" : "Rockadero", + "location": { + "latitude": 37.779632, + "longitude": -122.395131 + } + "created" : 1379975113142, + "modified" : 1379975113142, + "metadata" : { + "path" : "/restaurants/03ae956a-249f-11e3-9f80-d16344f5a0e1" + } + +## Querying location data +Location-aware apps require the ability to return content and results based on the user's current location. To easily enable this, API Services supports the following query parameter to retrieve entities within a specified distance of any geocoordinate based on its location property: + + location within of , + +The returned results are sorted from nearest to furthest. Entities with the same location are returned in the order they were created. + +The location parameter can be appended to any standard API Services query. For more information on how to query your API Services data, see [Querying your Data](../data-queries/querying-your-data.html). + +For example, here is how you would find all the devices within 8,046 meters (~10 miles) of the center of San Francisco: + + curl -X GET https://api.usergrid.com/your-org/your-app/devices?ql=location within 8046 of 37.774989,-122.419413 + +## Enrich your app with location data +Location-awareness has become a feature users expect in many types of mobile applications because of its ability to create a more personalized and relevant experience for each user. With this in mind, the geolocation feature in API Services was designed to work with many of the available [default data entities](../api-docs.html#models) to allow app developers to easily integrate powerful in-app features that can increase user engagement. + +Here are just a few of the ways that saving location data to a data entity can improve an app: + + + + + + + + + + + + + + + + + + + + + + +
EntityUsage
userSave the location of a user's home as part of their profile in the ``users`` collection to suggest upcoming special events or activities located nearby, or to display advertisements that are relevant based on the user's proximity to a business.
devicePeriodically save the location data returned from a user's device, then query the ``devices`` collection to send offers and alerts to user's that are located near your business with a [push notification](../push-notifications/push-notifications-overview).
activityCreate stronger social connections by associating a user ``activity`` with the location where it occurred. The activity can then be displayed to nearby friends and family, or used to enrich the user's activity stream.
assetSave user photos with location data in the ``asset collection`` to allow users to retrieve and sort their memories based on when and where they happened.
+ diff --git a/content/docs/_sources/geolocation/tbd.txt b/content/docs/_sources/geolocation/tbd.txt new file mode 100644 index 0000000000..279d128a63 --- /dev/null +++ b/content/docs/_sources/geolocation/tbd.txt @@ -0,0 +1 @@ +# COMING SOON... \ No newline at end of file diff --git a/content/docs/_sources/getting-started/creating-a-new-application.txt b/content/docs/_sources/getting-started/creating-a-new-application.txt new file mode 100644 index 0000000000..ce5fb7a829 --- /dev/null +++ b/content/docs/_sources/getting-started/creating-a-new-application.txt @@ -0,0 +1,16 @@ +# Creating a new application + +## Creating an application +You can use the admin portal to create applications. An application represents the data associated with your app. Through an application, you handle the entities associated with your app, including users, devices, events, and so on. + +To create a new application with the admin portal: + +1. In the admin portal, from the dropdown menu at the far top left, select the organization to which you will add the new application. +1. Click the ADD NEW APP button, located at the top of the screen, next to the application drop-down. +1. In the dialog box, enter a new application name, then click the Create button. Your new application will automatically be selected in the applications drop-down menu. + +Applications can also be created programatically with a ``POST`` request to the API. For more, see [Application](../orgs-and-apps/application.html). + +## Securing an application +If this is going to be a production application, be sure to configure security roles that provide only the level of access your users will need. For more on security, see [Security Best Practices](../security-and-auth/securing-your-app.html) +. \ No newline at end of file diff --git a/content/docs/_sources/getting-started/creating-account.txt b/content/docs/_sources/getting-started/creating-account.txt new file mode 100644 index 0000000000..f4f542a198 --- /dev/null +++ b/content/docs/_sources/getting-started/creating-account.txt @@ -0,0 +1,21 @@ +# Creating an Usergrid Account +To get started using the Usergrid, you'll need an Usergrid account. (Before reading this, you should already be familiar with what Usergrid can do to support your apps. If you're still curious about that, you might want to read Usergrid features first.) + +With an account, you get the following useful things: + +* A sandbox application you can try things with (we automatically create one for you with your new account). The sandbox is a partitioned area of the data store where you can add example data and try out API calls. The sandbox isn't secure, but it's handy to play in. For more about the sandbox, see [Using Your Application Sandbox](../getting-started/using-a-sandbox-app.html). +* The ability to create more applications (in addition to the sandbox). You can (and should!) make these as secure as you need to. These are the applications that you'll have behind the apps you make available to your users. +* Access to the Admin Portal. In the portal, you can do the following: +** Create and manage applications. +** Manage your app's users, including access levels. +** Manage the data in your app. +** Manage app features, including push notifications, activities, analytics, and so on. +** Try out API calls with a shell command window. +** To create an Usergrid account and see a very short tutorial to get started with, go to the get started page of the Portal. + +## Next steps +Ready to learn and do more? + +* Install an SDK that will be most useful for your application environment. For more about Usergrid's SDKs, see [SDKs](../sdks/tbd.html). +* Review Usergrid features for information on concepts and features. +* Consult the API Reference for usage details. \ No newline at end of file diff --git a/content/docs/_sources/getting-started/using-a-sandbox-app.txt b/content/docs/_sources/getting-started/using-a-sandbox-app.txt new file mode 100644 index 0000000000..75c296f5c8 --- /dev/null +++ b/content/docs/_sources/getting-started/using-a-sandbox-app.txt @@ -0,0 +1,39 @@ +# Using a Sandbox Application + +## What is the sandbox application? + +When you create a new Usergrid account (see [Creating an Usergrid Account](creating-account.html)) to use services for developers, Usergrid creates a new application for you on its servers. With the new application, called "sandbox," you can add your own example data and try out API calls that do things with the data. Be sure to see Using the API for suggestions. + +## Is the sandbox secure? + +To keep things simple and make it easier for you to try things out, the sandbox application has all authentication disabled. That way, it doesn’t require an access token for application-level calls to the API. Permissions are so open on the sandbox application because its "guest" role offers full permissions for all access paths -- that is, GET, POST, PUT, and DELETE for /**. Learn more about roles and permissions in Managing access by defining permission rules. + + +

Warning

+

Never use a sandbox app for production. +Keep in mind that the lack of authentication means that a sandbox application is not secure enough for important or sensitive data. A sandbox is just for experimentation while you learn how the services work, and should never be used for a production application. As with other Usergrid applications you create, a sandbox application is an area of the data store where you can put your own data. You can create as many other applications as you like, including more sandbox applications. When it comes to production (secured) applications, a good rule of thumb is to create one application for each mobile app you develop. +

+
+ +## Creating a New Sandbox Application + +You may want to create (or re-create) a sandbox application. For example, you may want to create a sandbox application for another organization or you may want to create another application for testing purposes. + + +

Warning

+Guest Role should never be given full permissions. +Giving the guest role full permissions should be used only for testing and should not be used in production. Before you make your app “live”, you should remove the guest permissions for /**. +

+ +Use the following steps to create a sandbox app: + +1. Create a new application using the admin portal. You can name the application whatever you like (including "sandbox"). +2. Set full access permissions for the guest role, as follows: + 1. In the admin portal, click Users, then click Roles. + 2. On the Roles page, in the list of roles, click Guest. + 3. For the Guest role, under Permissions, click Add Permission. + 4. In the New Permission dialog, enter the following in the Path box: ``/**`` + 5. Select the following check boxes: get, post, put, and delete. + 6. Click the Add button. + 7. If there are other permissions listed, delete them. + diff --git a/content/docs/_sources/getting-started/using-the-api.txt b/content/docs/_sources/getting-started/using-the-api.txt new file mode 100644 index 0000000000..d85f86a97c --- /dev/null +++ b/content/docs/_sources/getting-started/using-the-api.txt @@ -0,0 +1,150 @@ +# Using the API +Usergrid uses a pure REST (Representational State Transfer) API built as a collection of resources. Resource locations are described by paths that are related intrinsically to collections and entities in collections. + +This section gives several examples of how to construct API requests. To focus on what's important, the examples use an abbreviated path that starts after the application UUID, or application name. For example, instead of giving a fully qualified path name as in: + + https://api.usergrid.com/your-org/your-app/users + +the example simply lists this: + + /users + +## Supported HTTP methods +When building a REST API, the challenge is to represent the data and the action upon the data as a path to a resource that can be created, retrieved, updated, or deleted. The HTTP methods POST, GET, PUT, and DELETE correspond to the actions that are applied to resources. + +## Base URL +The base url for all requests made to Usergrid depends on where you have Usergrid installed. If you are using Apigee's trial Usergrid service, the base URL is ``https://api.usergrid.com.`` + +## Request construction +Usergrid interprets the URL resource path as a list of names, UUIDs, or queries. The basic path format is: + + https://api.usergrid.com//// + +Note: You cannot mix UUIDs and names in the URL resource path. For example, the following is incorrect: + + https://api.usergrid.com/your-org/62de5d97-d28c-11e1-8d5c-12313b01d5c1/users/john.doe + +## Accessing collections +To access all entities in a collection, specify the path as follows: + + /users + +Such a request retrieves the first 10 entities in the collection /users sorted by their entity UUID. + +## Accessing entities +To access an entity in a collection, specify the path as follows: + + // + +where ```` is the collection name, and is the entity’s uuid or name. + +To access a user in the users collection, specify the path as follows: + + /users/ + +where ```` is the user’s uuid, username, or email address. + +For example, the following request retrieves the entity named dino from the dogs collection: + + /dogs/dino + +## Issuing queries +You can issue a query in an API request that retrieves items from a collection. Here is the typical format for queries: + + /?ql= + +where is a query in the query language. + +For example, this request retrieves users whose Facebook first name is john: + + /users?ql=select * where facebook.first_name ='john' + +For further information about queries, see [Querying your Data](../data-queries/querying-your-data.html) + +## Authentication (OAuth) +Usergrid implements the OAuth 2.0 standard for authenticating users, clients and API requests. + +Generally, you will generate a token for every user of your app by providing the user's username and password. The token can then be sent with all API requests to ensure each user is only able to access and modify the resources you have granted them rights to. + +Note that by default access tokens are not needed to make requests to the default sandbox application in an organization. + +For more information on generating and using access tokens, see Authenticating users and application clients and Authenticating API requests. + +## Response format +All API methods return a response object that typically contains an array of entities: + + { + "entities" : [ + ... + ] + } + +Not everything can be included inside the entity, and some of the data that gets associated with specific entities isn't part of their persistent representation. This is metadata, and it can be part of the response as well as associated with a specific entity. Metadata is just an arbitrary key/value JSON structure. + +For example: + + { + "entities" : { + { + "name" : "ed", + "metadata" : { + "collections" : ["activities", "groups", "followers"] + } + } + }, + "metadata" : { + "foo" : ["bar", "baz"] + } + } + +For example, here is the response to a basic GET for a user entity: + + { + "action" : "get", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/users", + "uri" : "https://api.usergrid.com/your-org/your-app/users", + "entities" : [ { + "uuid" : "503f17da-ec39-11e3-a0dd-a554b7fbd57a", + "type" : "user", + "created" : 1401921665485, + "modified" : 1401921665485, + "username" : "someUser", + "email" : "someUser@yourdomain.com", + "activated" : true, + "picture" : "http://www.gravatar.com/avatar/dc5d478e9c029853fbd025bed0dc51f8", + "metadata" : { + "path" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a", + "sets" : { + "rolenames" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/roles", + "permissions" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/permissions" + }, + "collections" : { + "activities" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/activities", + "devices" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/devices", + "feed" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/feed", + "groups" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/groups", + "roles" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/roles", + "following" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/following", + "followers" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/followers" + } + } + } ], + "timestamp" : 1401921673597, + "duration" : 12, + "organization" : "your-org", + "applicationName" : "your-app" + } + +## SDKs +To make the integration of Usergrid features into your application code quicker and easier, Usegrid offers SDKs in a variety of languages. The SDKs contain language-specific methods that allow you to issue API requests from your application code in your preferred language. SDKs are available for the following languages: + +* iOS +* Android +* JavaScript/HTML5 +* Node.js +* Ruby +* .NET + +For more information, see SDKs. \ No newline at end of file diff --git a/content/docs/_sources/index.txt b/content/docs/_sources/index.txt new file mode 100644 index 0000000000..40054b7241 --- /dev/null +++ b/content/docs/_sources/index.txt @@ -0,0 +1,176 @@ +***************************** +Apache Usergrid Documentation +***************************** + +.. _intro:: + +.. toctree:: + :maxdepth: 2 + :caption: Getting Started + + introduction/overview.md + introduction/usergrid-features + introduction/data-model + introduction/async-vs-sync + +.. _using-usergrid: + +.. toctree:: + :maxdepth: 2 + :caption: Using Usergrid + + using-usergrid/creating-account + using-usergrid/creating-a-new-application + using-usergrid/using-a-sandbox-app + using-usergrid/using-the-api.md + +.. _data-storage: + +.. toctree:: + :maxdepth: 2 + :caption: Data Storage + + data-storage/data-store-dbms + data-storage/optimizing-access + data-storage/collections + data-storage/entities + +.. _data-queries: + +.. toctree:: + :maxdepth: 2 + :caption: Data Queries + + data-queries/querying-your-data + data-queries/query-parameters + data-queries/operators-and-types + data-queries/advanced-query-usage + +.. _entity-connections: + +.. toctree:: + :maxdepth: 2 + :caption: Entity Connections + + entity-connections/connecting-entities + entity-connections/retrieving-entities + entity-connections/disconnecting-entities + +.. _push-notifications: + +.. toctree:: + :maxdepth: 2 + :caption: Push Notifications + + push-notifications/overview + push-notifications/adding-push-support + push-notifications/getting-started + push-notifications/tutorial + push-notifications/registering + push-notifications/creating-notifiers + push-notifications/managing-users-and-devices + push-notifications/creating-and-managing-notifications + push-notifications/troubleshooting + +.. _security-and-authentication: + +.. toctree:: + :maxdepth: 2 + :caption: Security & Authentication + + security-and-auth/app-security + security-and-auth/using-permissions + security-and-auth/using-roles + security-and-auth/authenticating-users-and-application-clients + security-and-auth/user-authentication-types + security-and-auth/changing-token-time-live-ttl + security-and-auth/authenticating-api-requests + security-and-auth/revoking-tokens-logout + security-and-auth/facebook-sign + security-and-auth/securing-your-app + +.. _user-management-and-social-graph: + +.. toctree:: + :maxdepth: 2 + :caption: User Management & Social Graph + + user-management/user-management + user-management/working-user-data + user-management/group + user-management/activity + user-management/user-connections + user-management/messagee-example + +.. _geolocation: + +.. toctree:: + :maxdepth: 2 + :caption: Geo-location + + geolocation/geolocation + +.. _asset-and-file-management: + +.. toctree:: + :maxdepth: 2 + :caption: Assets & Files + + assets-and-files/uploading-assets.md + assets-and-files/retrieving-assets.md + assets-and-files/folders.md + +.. _counters-and-events: + +.. toctree:: + :maxdepth: 2 + :caption: Counters & Events + + counters-and-events/events-and-counters + counters-and-events/creating-and-incrementing-counters + counters-and-events/retrieving-counters + +.. _organization-and-application-management: + +.. toctree:: + :maxdepth: 2 + :caption: Organizations & Applications + + orgs-and-apps/managing + orgs-and-apps/organization + orgs-and-apps/application + orgs-and-apps/admin-user + +.. _rest-endpoints: + +.. toctree:: + :maxdepth: 0 + :caption: API Reference + + rest-endpoints/api-docs + +.. _sdks: + +.. toctree:: + :maxdepth: 2 + :caption: Client SDKs + + sdks/tbd + +.. _installation: + +.. toctree:: + :maxdepth: 2 + :caption: Installing Usergrid + + installation/deployment-guide + +.. _about: + +.. toctree:: + :maxdepth: 2 + :caption: More about Usergrid + + reference/presos-and-videos + reference/contribute-code + diff --git a/content/docs/_sources/installation/deployment-guide.txt b/content/docs/_sources/installation/deployment-guide.txt new file mode 100644 index 0000000000..bdde848a13 --- /dev/null +++ b/content/docs/_sources/installation/deployment-guide.txt @@ -0,0 +1,468 @@ +# Usergrid 2.1.0 (unreleased) Deployment Guide + +This document explains how to deploy the Usergrid v2.1.0 Backend-as-a-Service (BaaS), +which comprises the Usergrid Stack, a Java web application, and the Usergrid Portal, +which is an HTML5/JavaScript application. + + +## Intended audience + +You should be able to follow this guide if you are a developer, system admin or +operations person with some knowledge of Java application deployment and good +knowledge of Linux and the bash shell. + +This guide is a starting point and does NOT explain everything you need to know to +run Usergrid at-scale and in production. To do that you will need some additional +skills and knowledge around running, monitoring and trouble-shooting Tomcat +applications, multi-node Cassandra & ElasticSearch clusters and more. + + +## Prerequsites + +Below are the software requirements for Usergrid 2.1.0 Stack and Portal. +You can install them all on one computer for development purposes, and for +deployment you can deploy them separately using clustering. + + * Linux or a UNIX-like system (Usergrid may run on Windows, but we haven't tried it) + + * [Java SE 8 JDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html) + + * [Apache Tomcat 7+](https://tomcat.apache.org/download-70.cgi) + + * [Apache Cassandra 1.2.1+](http://cassandra.apache.org/download/) + + * [ElasticSearch 1.4+](https://www.elastic.co/downloads/elasticsearch) + +Optional but helpful: + + * An HTTP or REST client, such as [curl](http://curl.haxx.se) + * A web server such as [Apache HTTPD](https://httpd.apache.org) for running the Usergrid Portal + + +## Getting Started + +__Download the Apache Usergrid 2.1.0 binary release__ from the official Usergrid releases page: + +* [Apache Usergrid Releases](https://usergrid.apache.org/releases) + +When you un-tar the Usergrid binary release, you will see a directory layout like this: + + +-- apache-usergrid-2.1.0 + | + +-- LICENSE + | + +-- NOTICE + | + +-- CHANGELOG + | + +-- stack + | | + | + ROOT.war + | + +-- portal + | | + | +-- dist + | | + | + usergrid-portal.tar + | + +-- sdks + | | + | +-- html5-javascript (JavaScript SDK and source) + | | + | +-- java (Java SDK and source) + +The files that you need for deploying Usergrid Stack and Portal are `ROOT.war` and `usergrid-portal.tar`. + + +## Deploying the Usergrid Stack + +The Usergrid Stack is a Java EE web application that runs on Tomcat, +uses the Cassandra database for storage and the ElasticSearch search-engine for queries. + +Before installing the Usegrid Stack into Tomcat, you'll start by setting up the +required database and search engine nodes. + + +### Stack STEP #1: Setup Cassandra + +Usergrid needs access to at least one Apache Cassandra node. You can setup a single node of +Cassandra on your computer for development and testing. For production deployment, +a three or more node cluster is recommended. + +__Use the right Java.__ Cassandra requires Java and we recommend that you use the same version of Java +for Cassandra as you use to run Tomcat and ElasticSearch. + +__Refer to the__ [Apache Cassandra documentation](http://wiki.apache.org/cassandra/GettingStarted) +__for instructions on how to install Cassandra__. The [Datastax documentation for Cassandra 1.2](http://docs.datastax.com/en/cassandra/1.2/cassandra/features/featuresTOC.html) is also helpful. +Once you are up and running make a note of these things: + + * The name of the Cassandra cluster + * Hostname or IP address of each Cassandra node + * Port number used for Cassandra RPC (the default is 9160) + * Replication factor of Cassandra cluster + + +### Stack STEP #2: Setup ElasticSearch + +Usergrid also needs access to at least one ElasticSearch node. As with Cassandra, +you can setup single ElasticSearch node on your computer, and you should run +a cluster in production. + +__Use the right Java__. ElasticSearch requires Java and you *must* ensure that you use the +same version of Java for ElasticSearch as you do for running Tomcat. + +__Refer to the__ +[ElasticSearch 1.4 documentation](https://www.elastic.co/guide/en/elasticsearch/reference/1.4/index.html) +__for instructions on how to install__. Once you are up and running make a note of these things: + + * The name of the ElasticSearch cluster + * Hostname or IP address of each ElasticSearch node + * Port number used for ElasticSearch protocol (the default is 9200) + +__Running a single-node?__ If you are running a single-node ElasticSearch cluster then +you should set the number of replicas to zero, otherwise the cluster will report status YELLOW. + + curl -XPUT 'localhost:9200/_settings' -d '{"index" : { "number_of_replicas" : 0}}' + + +### Stack STEP #3: Setup Tomcat + +The Usergrid Stack is contained in a file named ROOT.war, a standard Java EE WAR +ready for deployment to Tomcat. On each machine that will run the Usergrid Stack +you must install the Java SE 8 JDK and Tomcat 7+. + +__Refer to the__ [Apache Tomcat 7](https://tomcat.apache.org/tomcat-7.0-doc/setup.html) __documentation for instructions on how to install__. Once Tomcat installed, you need to create and edit some configuration files. + + +### Stack STEP #4: Configure Usergrid Stack & Logging + +You must create a Usergrid properties file called `usergrid-deployment.properties`. +The properties in this file tell Usergrid how to communicate with Cassandra and +ElasticSearch, and how to form URLs using the hostname you wish to use for Usegrid. +There are many properties that you can set to configure Usergrid. + +Once you have created your Usergrid properties file, place it in the Tomcat lib directory. +On a Linux system, that directory is probably located at `/usr/share/tomcat7/lib`. + +__What goes in a properties file?__ + +The default properties file that is built into Usergrid contains the full list of properties, defaults and some documentation: + + * [The Default Usergrid Properties File](https://github.com/apache/usergrid/blob/master/stack/config/src/main/resources/usergrid-default.properties) + +You should review the defaults in the above file. To get you started, let's look at a minimal example properties file that you can edit and use as your own. + + +#### Example Usergrid Stack Properties File + +Below is an minimal example Usergrid properties file with the parts you need to change indicated like +shell variables, e.g. `${USERGRID_CLUSTER_NAME}`. + +Example 1: usergrid-deployment.properties file + + usergrid.cluster_name=${USERGRID_CLUSTER_NAME} + + cassandra.url=${CASSANDRA_HOSTS} + cassanrda.cluster=${CASSANDRA_CLUSTER_NAME} + + elasticsearch.cluster_name=${ELASTICSEARCH_CLUSTER_NAME} + elasticsearch.hosts=${ELASTIC_SEARCH_HOSTS} + + ###################################################### + # Admin and test user setup + + usergrid.sysadmin.login.allowed=true + usergrid.sysadmin.login.name=superuser + usergrid.sysadmin.login.password=${SUPER_USER_PASSWORD} + usergrid.sysadmin.login.email=${SUPER_USER_EMAIL} + + usergrid.sysadmin.email=${SUPER_USER_EMAIL} + usergrid.sysadmin.approve.users=true + usergrid.sysadmin.approve.organizations=true + + # Base mailer account - default for all outgoing messages + usergrid.management.mailer=Admin <${SUPER_USER_EMAIL}> + + usergrid.setup-test-account=true + usergrid.test-account.app=test-app + usergrid.test-account.organization=test-organization + usergrid.test-account.admin-user.username=test + usergrid.test-account.admin-user.name=Test User + usergrid.test-account.admin-user.email=${TEST_ADMIN_USER_EMAIL} + usergrid.test-account.admin-user.password=${TEST_ADMIN_USER_PASSWORD} + + ###################################################### + # Auto-confirm and sign-up notifications settings + + usergrid.management.admin_users_require_confirmation=false + usergrid.management.admin_users_require_activation=false + + usergrid.management.organizations_require_activation=false + usergrid.management.notify_sysadmin_of_new_organizations=true + usergrid.management.notify_sysadmin_of_new_admin_users=true + + ###################################################### + # URLs + + # Redirect path when request come in for TLD + usergrid.redirect_root=${BASEURL}/status + + usergrid.view.management.organizations.organization.activate=${BASEURL}/accounts/welcome + usergrid.view.management.organizations.organization.confirm=${BASEURL}/accounts/welcome + + usergrid.view.management.users.user.activate=${BASEURL}/accounts/welcome + usergrid.view.management.users.user.confirm=${BASEURL}/accounts/welcome + + usergrid.admin.confirmation.url=${BASEURL}/management/users/%s/confirm + usergrid.user.confirmation.url=${BASEURL}/%s/%s/users/%s/confirm + usergrid.organization.activation.url=${BASEURL}/management/organizations/%s/activate + usergrid.admin.activation.url=${BASEURL}/management/users/%s/activate + usergrid.user.activation.url=${BASEURL}%s/%s/users/%s/activate + + usergrid.admin.resetpw.url=${BASEURL}/management/users/%s/resetpw + usergrid.user.resetpw.url=${BASEURL}/%s/%s/users/%s/resetpw + + +Here's a guide to the things you need to set in the above properties file. + +__Table 1: Values to set in Example Properties file:__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueDescription
__BASEURL__This is the base URL for the Usergrid installation, e.g. `https://api.example.com`.
__USERGRID_CLUSTER_NAME__This is your name for your Usergrid installation.
__CASSANDRA_CLUSTER_NAME__Name of Cassandra cluster, must match what's in Cassandra configuration.
__CASSANDRA_HOSTS__Comma-separated lists of Cassandra hosts, with port numbers if you are not using the default 9160. The default for this property is `localhost:9160`
__ELASTICSEARCH_CLUSTER_NAME__Name of ElasticSearch cluster, must match what's in ElasticSearch configuration.
__ELASTICSEARCH_HOSTS__Comma-separated lists of ElasticSearch hosts, with port numbers if you are not using the default 9300. The default for this property is `localhost:9300`
__SUPER_USER_EMAIL__Email address of person responsible for the superuser account.
__SUPER_USER_PASSWORD__Password for the superuser account.
__TEST_ADMIN_USER_EMAIL__If `usergrid.setup-test-account=true`, as shown below, Usergrid will create a test account and you should specify a valid email here.
__TEST_ADMIN_USER_PASSWORD__Password for the username 'test' account.
+ +Make sure you set all of the above properties when you edit this example for your installation. + + +#### Configure Logging + +Usegrid includes the Apache Log4j logging system and you can control the levels of logs for each +Usergrid package and even down to the class level by providing your own `log4j.properties` file. + +To configure logging you need to: + +1. Create a `log4j.properties` file and place it on the computer where Tomcat is running +2. Add `-D` system property to Tomcat so that Tomcat can find your Log4j properties file. + + +##### Example Logging Configuration + +The Log4j properties file below is a good starting point for Usergrid. It configures `ERROR` level +logging for the 3rd party libraries that Usergrid depends on, and INFO level logging for Usergrid. +Plus, it configures some noisy parts of Usergrid to be quiet. + +Example 2: log4.properties file + + # output messages into a rolling log file as well as stdout + log4j.rootLogger=ERROR,stdout + + # stdout + log4j.appender.stdout=org.apache.log4j.ConsoleAppender + log4j.appender.stdout.layout=org.apache.log4j.PatternLayout + log4j.appender.stdout.layout.ConversionPattern=%d %p (%t) [%c] - %m%n + + log4j.logger.org.apache.usergrid=INFO + + log4j.logger.me.prettyprint.cassandra.hector.TimingLogger=WARN + log4j.logger.org.apache.usergrid.rest.security.AllowAjaxFilter=WARN + log4j.logger.me.prettyprint.hector.api.beans.AbstractComposite=ERROR + + +##### Add Logging Configuration to Tomcat + +You can configure Tomcat to use your Log4j properties file but adding a system property to Tomcat +named `log4j.configuration` which must be set to a `file:/` URL that points to your +properties file. One way to add the above property to the Tomcat start-up is to add a line to a +Tomcat `setenv.sh` script in Tomcat's bin directory. If that file does not exist, then create it. + +For example, if your property file is in `/usr/share/tomcat7/lib/log4j.properties`, then you +would add the following line to `setenv.sh`: + + export JAVA_OPTS="-Dlog4j.configuration=file:///usr/share/tomcat7/lib/log4j.properties" + +If the file already exists and already sets the JAVA_OPTS variable, then you'll have to +add your `-D` option to ones already there. Also note, you might want set other `-D` and `-X` +options in that setenv file, e.g. Java heap size. + + +### Stack STEP #5: Deploy ROOT.war to Tomcat + +The next step is to deploy the Usergrid Stack software to Tomcat. There are a variey of ways +of doing this and the simplest is probably to place the Usergrid Stack `ROOT.war` file into +the Tomcat `webapps` directory, then restart Tomcat. + + +__For example, on Linux...__ + +You would probabaly copy the ROOT.war file like so: + + cp ROOT.war /usr/share/tomcat7/webapps + +And you would restart Tomcat 7 like so: + + /etc/init.d/tomcat7 restart + +You can watch the Tomcat log in `/var/log/tomcat7/catalina.out` for errors: + + tail -f /var/log/tomcat7/catalina.out + + Look for messages like this, which indicate that the ROOT.war file was deployed: + + INFO: Starting service Catalina + Jan 29, 2016 1:00:32 PM org.apache.catalina.core.StandardEngine startInternal + INFO: Starting Servlet Engine: Apache Tomcat/7.0.59 + Jan 29, 2016 1:00:32 PM org.apache.catalina.startup.HostConfig deployWAR + INFO: Deploying web application archive /usr/share/tomcat7/webapps/ROOT.war + + +__Does it work?__ + +Check to see if Usergrid is up and running by calling the status end-point. +If your web browser is running on the same computer as Tomcat (and Tomcat is on port 8080), +then you can browse to [http://localhost:8080/status](http://localhost:8080/status) +to view the Usergrid status page. + +Or you can use curl: + + curl http://localhost:8080/status + +If you get a JSON file of status data, then you're ready to move to the next step. +You should see a response that begins like this: + + { + "timestamp" : 1454090178953, + "duration" : 10, + "status" : { + "started" : 1453957327516, + "uptime" : 132851437, + "version" : "201601240200-595955dff9ee4a706de9d97b86c5f0636fe24b43", + "cassandraAvailable" : true, + "cassandraStatus" : "GREEN", + "managementAppIndexStatus" : "GREEN", + "queueDepth" : 0, + "org.apache.usergrid.count.AbstractBatcher" : { + "add_invocation" : { + "type" : "timer", + "unit" : "microseconds", + + ... etc. ... + + +#### Initialize the Usergrid Database + +Next, you must initialize the Usergrid database, index and query systems. + +To do this you must issue a series of HTTP operations using the superuser credentials. +You can only do this if Usergrid is configured to allow superused login via +this property `usergrid.sysadmin.login.allowed=true` and if you used the +above example properties file, it is allowed. + +The three operation you must perform are expressed by the curl commands below and, +of course, you will have ot change the password 'test' to match the superuser password +that you set in your Usergrid properties file. + + curl -X PUT http://localhost:8080/system/database/setup -u superuser:test + curl -X PUT http://localhost:8080/system/database/bootstrap -u superuser:test + curl -X GET http://localhost:8080/system/superuser/setup -u superuser:test + +When you issue each of those curl commands, you should see a success message like this: + + { + "action" : "cassandra setup", + "status" : "ok", + "timestamp" : 1454100922067, + "duration" : 374 + } + +If you don't see a success message, then refer to the Tomcat logs for error message and +seek help from the [Usergrid community](http://usergrid.apache.org/community). + +Now that you've gotten Usergrid up and running, you're ready to deploy the Usergrid Portal. + + +## Deploying the Usergrid Portal + +The Usergrid Portal is an HTML5/JavaScript application, a bunch of static files that +can be deployed to any web server, e.g. Apache HTTPD or Tomcat. + +To deploy the Portal to a web server, you will un-tar the `usergrid-portal.tar` file into +directory that serves as the root directory of your web pages. + +For example, with Tomcat on Linux you might do something like this: + + cp usergrid-portal.tar /usr/share/tomcat7/webapps + cd /usr/share/tomcat7/webapps + tar xf usergrid-portal.tar + +Then you will probably want to rename the Portal directory to something that will work +well in a URL. For example, if you want your Portal to exist at the path `/portal` then: + + mv usergrid-portal.2.0.18 portal + +Once you have done that there is one more step. You need to configure the portal so that +it can find the Usergrid stack. You do that by editing the `portal/config.js` and changing +this line: + + Usergrid.overrideUrl = 'http://localhost:8080/'; + +To set the hostname that you will be using for your Usergrid installation. + +Start your web server and Portal should be up and running at http://localhost:8080/portal or wherever you deployed it. + + + +## Additional Resources + +Resources that might be useful to those deploying Usergrid: + +[Usergrid-Vagrant](https://github.com/snoopdave/usergrid-vagrant): A VagrantFile and set of bash scripts that will launch a Linux Virtual Machine running Cassandra, ElasticSearch, Tomcat and the Usergrid 2.1 Stack and Portal. + +[Usergrid AWS Cluster](https://github.com/apache/usergrid/tree/master/deployment/aws): An AWS Cloud Formation template and supporting scripts that create a set of multiple EC2 instances running Usergrid Stack/Portal and a set of EC2 instances running Cassandra and ElasticSearch. + + +## The End + +That's all folks. diff --git a/content/docs/_sources/installation/ug1-deploy-to-tomcat.txt b/content/docs/_sources/installation/ug1-deploy-to-tomcat.txt new file mode 100644 index 0000000000..4c88387d4f --- /dev/null +++ b/content/docs/_sources/installation/ug1-deploy-to-tomcat.txt @@ -0,0 +1,179 @@ +# Usegrid 1: Deploying to Tomcat + +This is a guide that explains how to install and run Usergrid using stock Tomcat and Cassandra on a single computer. + +NOTE: running Cassandra on a single computer is something you should do ONLY for testing purposes. You don't want to run one node in production even just to start out. To get the benefit of Cassandra's architecture, which is designed to support linear scalability. You should be running a Cassandra cluster with at least three nodes. + +For more information: + +* [Cassandra FAQ: Can I Start With a Single Node?](http://planetcassandra.org/blog/post/cassandra-faq-can-i-start-with-a-single-node/) +* [Why don't you start off with a “single & small” Cassandra server](http://stackoverflow.com/questions/18462530/why-dont-you-start-off-with-a-single-small-cassandra-server-as-you-usually) + +## Requirements + +* [JDK 1.7](http://www.oracle.com/technetwork/java/javase/downloads/index.html) +* [Maven](http://maven.apache.org/) + +## Download + +Use GitHub to clone the [apache/usergrid](https://github.com/apache/usergrid) repo. + +Or you can start by [downloading our latest code](https://github.com/apache/usergrid/archive/master.zip) and extract it. + +## Building + +From the command line, navigate to `stack` directory and type the following: + + mvn clean package -DskipTests=true + +Once you are done the Usergrid application will be package as a Java EE WAR file at the location __stack/rest/target/ROOT.war__. + +Install and configure Cassandra +--- + +Install Cassandra, don't edit configuration files as we just want default values for this simple setup. Here are the [instructions for installing Cassandra](http://wiki.apache.org/cassandra/GettingStarted) + +Install and configure Tomcat +--- + +Follow instructions, don't edit configuration files as we just want default values for this simple setup. Here are the [instructions for installing Tomcat 7](http://tomcat.apache.org/tomcat-7.0-doc/setup.html) + +Add Usergrid WAR to Tomcat +--- + +Remove the existing `tomcat/webapps/ROOT` directory. + +Place the Usergrid `ROOT.war` file into the `tomcat/webapps` directory + +Add Usergrid configuration file to Tomcat +--- + +Create a ____usergrid-custom.properties____ file and place it in Tomcat's __lib__ directory. You can find an example properties file below that should work well for a local Tomcat & Cassandra setup. You will probably only need to change the properties below to use your email address and preferred password for the install. + + + usergrid.sysadmin.login.allowed=true + usergrid.sysadmin.login.name=superuser + usergrid.sysadmin.login.password=pw123 + usergrid.sysadmin.email=me@example.com + usergrid.sysadmin.login.email=myself@example.com + usergrid.management.mailer=Myself + usergrid.test-account.admin-user.email=myself@example.com + usergrid.test-account.admin-user.password=test + +Run Usergrid Database & Super User Setup +--- + +Start Tomcat and use your web browser to visit the URLs below. While you do this you might want to watch the logs under tomcat/logs for clues, just in case anything goes wrong. + +Database setup URL - [http://localhost:8080/system/database/setup](http://localhost:8080/system/database/setup) + +When prompted to login use the sysadmin credentials that you specified in your __usergrid-custom.properties__ file. Based on the example above that would be superuser and pw123. If the operation is successful you should a message like the one below in your browser. If not, check your logs for clues about what went wrong. + + { + "action" : "cassandra setup", + "status" : "ok", + "timestamp" : 1379424622947, + "duration" : 76 + } + +Superuser setup URL - [http://localhost:8080/system/superuser/setup](http://localhost:8080/system/superuser/setup) + +You should not be prompted for login because you already logged into for the Database Setup. If setup works, you should see a message like this: + + { + "action" : "superuser setup", + "status" : "ok", + "timestamp" : 1379424667936, + "duration" : 2 + } + +Build the Usergrid Console +--- +The Usergrid Console is an admin interface written in JavaScript that connects to your running Usergrid instance. For evaluation purposes, you can run it within Tomcat. Build it by following the steps [here](https://github.com/apache/usergrid/blob/master/portal/README.md). Once built, copy the directory _portal/build/usergrid-portal_ to _tomcat/webapps_. + + +Login to the Usergrid Console & get started +--- +You should now be able to login to the Usergrid console and start configuring applications, users and more. + +You can use an static version of the portal to get started: + +http://localhost:8080/usergrid-portal/(http://localhost:8080/usergrid-portal) + + +Example __usergrid-custom.properties__ file +--- +Here's a complete example properties file to get you started. + + # Minimal Usergrid configuration properties for local Tomcat and Cassandra + # + # The cassandra configuration options. + + # The cassandra host to use + cassandra.url=localhost:9160 + + # if your cassandra instance requires username/password + cassandra.username=someuser + cassandra.password=somepassword + + # The strategy to use when creating the keyspace. This is the default. + # We recommend creating the keyspace with this default, then editing it + # via the cassandra CLI to meet the client's needs. + cassandra.keyspace.strategy=org.apache.cassandra.locator.SimpleStrategy + + # The default replication factor for the simple strategy. Again, leave the + # default, create the app, then use the cassandra cli to set the replication + # factor options. This can become complicated with different topologies and + # is more a Cassandra administration issue than a UG issue. + cassandra.keyspace.strategy.options.replication_factor=1 + + ###################################################### + # Custom mail transport. Not usually used for local testing + + #mail.transport.protocol=smtps + #mail.smtps.host=email-smtp.us-east-1.amazonaws.com + #mail.smtps.port=465 + #mail.smtps.auth=true + #mail.smtps.quitwait=false + #mail.smtps.username= + #mail.smtps.password= + + ###################################################### + # Admin and test user setup (change these to be their super user + + usergrid.sysadmin.login.name=superuser + usergrid.sysadmin.login.email=myself@example.com <--- Change this + usergrid.sysadmin.login.password=pw123 <--- Change this + usergrid.sysadmin.login.allowed=true + usergrid.sysadmin.email=myself@example.com <--- Change this + + # Enable or disable this to require superadmin approval of users + usergrid.sysadmin.approve.users=false + + ###################################################### + # Auto-confirm and sign-up notifications settings + + usergrid.management.admin_users_require_confirmation=false + usergrid.management.admin_users_require_activation=false + usergrid.management.organizations_require_activation=false + usergrid.management.notify_sysadmin_of_new_organizations=false + usergrid.management.notify_sysadmin_of_new_admin_users=false + + ###################################################### + # URLs + # Redirect path when request come in for TLD + + usergrid.redirect_root=https://localhost:8080/status + usergrid.view.management.organizations.organization.activate=https://localhost:8080/accounts/welcome + usergrid.view.management.organizations.organization.confirm=https://localhost:8080/accounts/welcome + usergrid.view.management.users.user.activate=https://localhost:8080/accounts/welcome + usergrid.view.management.users.user.confirm=https://localhost:8080/accounts/welcome + usergrid.organization.activation.url=https://localhost:8080/management/organizations/%s/activate + usergrid.admin.activation.url=https://localhost:8080/management/users/%s/activate + usergrid.admin.resetpw.url=https://localhost:8080/management/users/%s/resetpw + usergrid.admin.confirmation.url=https://localhost:8080/management/users/%s/confirm + usergrid.user.activation.url=https://localhost:8080%s/%s/users/%s/activate + usergrid.user.confirmation.url=https://localhost:8080/%s/%s/users/%s/confirm + usergrid.user.resetpw.url=https://localhost:8080/%s/%s/users/%s/resetpw + + \ No newline at end of file diff --git a/content/docs/_sources/installation/ug1-launcher-quick-start.txt b/content/docs/_sources/installation/ug1-launcher-quick-start.txt new file mode 100644 index 0000000000..fe25e215c3 --- /dev/null +++ b/content/docs/_sources/installation/ug1-launcher-quick-start.txt @@ -0,0 +1,72 @@ +# Usegrid 1: Launcher Quick-start + +## Requirements + +* [JDK 1.7](http://www.oracle.com/technetwork/java/javase/downloads/index.html) +* [Maven](http://maven.apache.org/) + +## Download + +### Download2 + +Start by [downloading our latest code](https://github.com/apache/usergrid/archive/master.zip) and extract it. + +#### Building 3 + +From the command line, navigate to stack directory and type the following: + + mvn clean install -DskipTests=true + +## Running + +Usergrid-core contains the persistence layer and shared utilities for powering the Usergrid service. The services layer is contained in usergrid-services and exposes a higher-level API that's used by the usergrid-rest web services tier. + +You can run Usergrid from the command-line from the +jar in the usergrid/standalone project: + + cd launcher; java -jar target/usergrid-launcher-*.jar + +After startup, your instance will be available on localhost, port 8080. +To check it’s running properly, you can try loading our status page: + + curl http://localhost:8080/status + +You can also run it as a webapp in Tomcat, by deploying the ROOT.war file generated in the usergrid/rest project. + +## Getting Started with the HTTP API + +Start by creating an Organization. It’s the top-level structure in Usergrid: +all Apps and Administrators must belong to an Organization. Here’s how you create one: + + curl -X POST \ + -d 'organization=myfirstorg&username=myadmin&name=Admin&email=admin@example.com&password=password' \ + http://localhost:8080/management/organizations + +You can see that creating an Organization creates an Administrator in the process. Let’s authenticate as him: + + curl 'http://localhost:8080/management/token?grant_type=password&username=myadmin&password=password' + +This will return an access\_token. We’ll use this to authenticate the next two calls. +Next, let’s create an Application: + + curl -H "Authorization: Bearer [the management token from above]" \ + -H "Content-Type: application/json" \ + -X POST -d '{ "name":"myapp" }' \ + http://localhost:8080/management/orgs/myfirstorg/apps + +… And a User for the Application: + + curl -H "Authorization: Bearer [the management token from above]" \ + -X POST "http://localhost:8080/myfirstorg/myapp/users" \ + -d '{ "username":"myuser", "password":"mypassword", "email":"user@example.com" }' + +Let’s now generate an access token for this Application User: + + curl 'http://localhost:8080/myfirstorg/myapp/token?grant_type=password&username=myuser&password=mypassword' + +This will also send back an access\_token, but limited in scope. +Let’s use it to create a collection with some data in it: + + curl -H "Authorization: Bearer [the user token]" \ + -X POST -d '[ { "cat":"fluffy" }, { "fish": { "gold":2, "oscar":1 } } ]' \ + http://localhost:8080/myfirstorg/myapp/pets diff --git a/content/docs/_sources/installation/ug2-deploy-to-tomcat.txt b/content/docs/_sources/installation/ug2-deploy-to-tomcat.txt new file mode 100644 index 0000000000..752b4f3a34 --- /dev/null +++ b/content/docs/_sources/installation/ug2-deploy-to-tomcat.txt @@ -0,0 +1,181 @@ +# Usergrid 2: Deploy to Tomcat + +__NOTE__: Beware that Usergrid 2 is UNRELEASED SOFTWARE + + +## Requirements + +* [JDK 1.8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) +* [Maven 3.2+](http://maven.apache.org/) +* [Tomcat 7+](https://tomcat.apache.org/download-70.cgi) +* [Cassandra 1.2.1*](http://cassandra.apache.org/download/) +* [ElasticSearch 1.4+](https://www.elastic.co/downloads/elasticsearch) +* [Usergrid 2.1](https://github.com/apache/usergrid/tree/2.1-release) + +## Running + +1. Start up Cassandra [^1] + a. To do this you can navigate to the cassandra folder and run ```./bin/cassandra ``` +2. Start up Elasticsearch + a. To do this you can navigate to the folder where you extracted elasticsearch and run ```/bin/elasticsearch``` + +### Running Usergrid + +#### Build The Java SDK + +1. Navigate to where you cloned the usergrid repo +2. Navigate to the ```sdks/java``` directory +3. Run ```mvn clean install``` + +#### Build The Stack Itself + +1. Navigate to the ```stack``` directory. +2. Run ```mvn clean install -DskipTests``` +3. This will generate a war at ```rest/target/ROOT.war``` + +#### Deploying the Stack Locally + +1. Take this war and deploy it on downloaded tomcat. +1. In the lib directory of the tomcat you must also put usergrid-deployment.properties. ( An example file is provided below) +1. Start up Tomcat + a. To do this you can navigate to folder where Tomcat is install and run ```./bin/catalina.sh start``` + +Next, you need to make some API calls to initialize Usergrid's storage and indexing systems. You can make these +API calls using curl or your favorite HTTP client. These calls can only be done with the superuser credentials +that appear in your __usergrid-deployment.properties__ file. Here's how to do the calls with curl (and assuming +your superuser password is 'test'): + + curl -X PUT http://localhost:8080/system/database/setup -u superuser:test + curl -X PUT http://localhost:8080/system/database/bootstrap -u superuser:test + curl -X GET http://localhost:8080/system/superuser/setup -u superuser:test + +Once those three calls execute without error, then you are done. If you do see errors the double-check that you +have Cassandra and ElasticSearch running and that your properties files lists your Cassandra and ElasticSearch +hostnames correctly. Also check that ElasticSearch cluster name (in elasticsearch.yml) matches the one in the +Usergrid properties file. If the problem persists come talk to us on the Usergrid mailing list, we might be able to help. + +The stack is now ready to be queried against, but to get the most out of it you'll need to initialize and use our portal! + +#### Running The Portal Locally + +##### Requirments + +[nodejs 0.10+](https://nodejs.org/download/) + +1. Make sure you've installed node.js above. Any version above .10 or .10 should work fine. +2. Navigate to ```usergrid/portal```. +3. Open config.js and make sure the override URL is pointing to your local tomcat. +4. Now in the portal folder run the following command ```./build.sh dev``` +5. The portal should automatically open ready for use! + +Now usergrid is fully ready to use! Feel free to query against it or use it however you like! + + +Example __usergrid-deployment.properties__ file +--- +``` +# core persistence properties + +usergrid.cluster_name property=usergrid + +cassandra.embedded=false +cassandra.version=1.2.18 +cassandra.timeout=2000 + +collections.keyspace=Usergrid_Applications +collections.keyspace.strategy.options=replication_factor:1 +collections.keyspace.strategy.class=org.apache.cassandra.locator.SimpleStrategy + +collection.stage.transient.timeout=60 + +hystrix.threadpool.graph_user.coreSize=40 +hystrix.threadpool.graph_async.coreSize=40 + +elasticsearch.embedded=false +elasticsearch.cluster_name=elasticsearch +elasticsearch.index_prefix=usergrid +elasticsearch.hosts=127.0.0.1 +elasticsearch.port=9300 + +elasticsearch.force_refresh=true + +index.query.limit.default=100 + +# Max Cassandra connections, applies to both CP and EM +cassandra.connections=600 + +###################################################### +# Minimal Usergrid configuration properties for local Tomcat and Cassandra +# + +cassandra.url=127.0.0.1:9160 + +cassandra.keyspace.strategy=org.apache.cassandra.locator.SimpleStrategy +cassandra.keyspace.strategy.options.replication_factor=1 + +###################################################### +# Custom mail transport + +mail.transport.protocol=smtps +mail.smtps.host=smtp.gmail.com +mail.smtps.port=465 +mail.smtps.auth=true +mail.smtps.username= +mail.smtps.password= +mail.smtps.quitwait=false + + +###################################################### +# Admin and test user setup + +usergrid.sysadmin.login.name=superuser +usergrid.sysadmin.login.email=myself@example.com <--- Change this +usergrid.sysadmin.login.password=pwHERE <--- Change this +usergrid.sysadmin.login.allowed=true +usergrid.sysadmin.email=myself@example.com <--- Change this + +usergrid.sysadmin.approve.users=false +usergrid.sysadmin.approve.organizations=false + +# Base mailer account - default for all outgoing messages +usergrid.management.mailer=User <--- Change this + +usergrid.setup-test-account=true + +usergrid.test-account.app=test-app +usergrid.test-account.organization=test-organization +usergrid.test-account.admin-user.username=test +usergrid.test-account.admin-user.name=Test User +usergrid.test-account.admin-user.email=myself@example.com <---Change this +usergrid.test-account.admin-user.password=test + +###################################################### +# Auto-confirm and sign-up notifications settings + +usergrid.management.admin_users_require_confirmation=false +usergrid.management.admin_users_require_activation=false + +usergrid.management.organizations_require_activation=false +usergrid.management.notify_sysadmin_of_new_organizations=true +usergrid.management.notify_sysadmin_of_new_admin_users=true +###################################################### +# URLs + +# Redirect path when request come in for TLD +usergrid.redirect_root=http://localhost:8080/status + +usergrid.view.management.organizations.organization.activate=http://localhost:8080/accounts/welcome +usergrid.view.management.organizations.organization.confirm=http://localhost:8080/accounts/welcome +usergrid.view.management.users.user.activate=http://localhost:8080/accounts/welcome +usergrid.view.management.users.user.confirm=http://localhost:8080/accounts/welcome + +usergrid.organization.activation.url=http://localhost:8080/management/organizations/%s/activate +usergrid.admin.activation.url=http://localhost:8080/management/users/%s/activate +usergrid.admin.resetpw.url=http://localhost:8080/management/users/%s/resetpw +usergrid.admin.confirmation.url=http://localhost:8080/management/users/%s/confirm +usergrid.user.activation.url=http://localhost:8080%s/%s/users/%s/activate +usergrid.user.confirmation.url=http://localhost:8080/%s/%s/users/%s/confirm +usergrid.user.resetpw.url=http://localhost:8080/%s/%s/users/%s/resetpw +``` + +[^1]: You can start up cassandra and elasticsearch in any order but for the sake of ordered lists I put Cassandra first. \ No newline at end of file diff --git a/content/docs/_sources/introduction/async-vs-sync.txt b/content/docs/_sources/introduction/async-vs-sync.txt new file mode 100644 index 0000000000..fe1f721c85 --- /dev/null +++ b/content/docs/_sources/introduction/async-vs-sync.txt @@ -0,0 +1,25 @@ +# Async vs. sync calls +The Usergrid SDKs work by making RESTful API calls from your application to the API. In some cases, both synchronous and asynchronous calls are supported for most methods, as in the case of the Usergrid Android SDK, while in others only asynchronous calls are supported, as in the Usergrid JavaScript SDK. The following is a brief explanation of synchronous vs. asynchronous API calls. + +## Synchronous +If an API call is synchronous, it means that code execution will block (or wait) for the API call to return before continuing. This means that until a response is returned by the API, your application will not execute any further, which could be perceived by the user as latency or performance lag in your app. Making an API call synchronously can be beneficial, however, if there if code in your app that will only execute properly once the API response is received. + +## Asynchronous +Asynchronous calls do not block (or wait) for the API call to return from the server. Execution continues on in your program, and when the call returns from the server, a "callback" function is executed. For example, in the following code using the Usergrid JavScript SDK, the function called dogCreateCallback will be called when the create dog API call returns from the server. Meanwhile, execution will continue: + + function dogCreateCallback(err, dog) { + alert('I will probably be called second'); + if (err) { + //Error - Dog not created + } else { + //Success - Dog was created + + } + } + + client.createEntity({type:'dogs'}, dogCreateCallback); + alert('I will probably be called first'); + +The result of this is that we cannot guarantee the order of the two alert statements. Most likely, the alert right after the createEntity function call will be called first since the API call will take a second or so to complete. + +The important point is that program execution will continue, and asynchronously, the callback function will be called once program execution completes. \ No newline at end of file diff --git a/content/docs/_sources/introduction/data-model.txt b/content/docs/_sources/introduction/data-model.txt new file mode 100644 index 0000000000..41421bd20a --- /dev/null +++ b/content/docs/_sources/introduction/data-model.txt @@ -0,0 +1,76 @@ +# Usergrid Data model + +Usergrid models the data for your apps as application-specific collections of data entities managed within an organization. The following is an overview of the component hierarchy that makes up the data model, and is intended to help you understand how data is stored, managed and accessed. + +## Organizations +An organization contains one or more applications, and represents administrator-level access. Multiple accounts may be given administrator access to an organization. Accounts can also be members of multiple organizations. + +An organization with the same name as your username is automatically created for you when you sign up. By default, you are assigned as the administrator of this organization. + +## Applications +In Usergrid, you can create one or more applications within an organization. Applications represent an instance of application data associated with an app, and you may create as many applications as you wish. This allows you to utilize the backend in a way that corresponds to your development process. For example, you might create separate applications for development and production instances of your app. By default, all organization have a sandbox application (see Using a [Sandbox Application](../getting-started/using-a-sandbox-app.html) for important information regarding the default sandbox application). + +Each application provides the infrastructure for storing, retrieving, updating and deleting the entities and collections associated with a specific app instance. + +## Collections +Usergrid stores all data entities in uniquely-named collections. Collections are created automatically for every entity type, including custom entities, and are named using the plural form of the entity type they store. For example, all user entities are stored in the /users collection, and all device entities in the /devices collection. An entity can belong to only one collection. + +Currently, collections cannot be renamed or deleted; however, all of the data entities in a collection can be updated or deleted. + +## Entities +An entity represents a basic, JSON-formatted data object that is used by your app, such as a user, device, event or asset. Unlike records in conventional database tables, which have a rigid schema that defines what they can store and how they can be related to each other, Usergrid entities are very flexible. This makes Usergrid a powerful solution for managing data for modern applications, where people, places, and content often need to be associated in a way that is most appropriate from a user perspective. + +Here is a simple example of an entity: + + { + "uuid" : "5c0c1789-d503-11e1-b36a-12313b01d5c1", + "type" : "user", + "created" : 1343074620374, + "modified" : 1355442681264, + "username" : "john.doe", + "email" : "jdoe57@mail.com", + "name" : "John Doe" + } + +## Default entities +The following entity types are predefined in Usergrid. For more details, see the [API Reference](../rest-endpoints/api-docs.html) + +* [user](../rest-endpoints/api-docs.html#user) +* [group](../rest-endpoints/api-docs.html#group) +* [role](../rest-endpoints/api-docs.html#role) +* [application](../rest-endpoints/api-docs.html#application) +* [activity](../rest-endpoints/api-docs.html#activity) +* [device](../rest-endpoints/api-docs.html#device) +* [asset](../rest-endpoints/api-docs.html#asset) +* [folder](../rest-endpoints/api-docs.html#folder) +* [event](../rest-endpoints/api-docs.html#event) +* [notifier](../rest-endpoints/api-docs.html#notifier) +* [notification](../rest-endpoints/api-docs.html#notification) +* [receipt](../rest-endpoints/api-docs.html#recept) + +## Properties + +A data entity is a set of properties, which can each contain any JSON-representable value, including a nested JSON document. All entities have predefined properties, but you are free to define any number of custom properties for any entity. Default properties require specific data types for validation purposes, while custom properties can be any JSON data type. Most predefined and all application-defined entity properties are indexed, allowing you to query collections quickly and easily. + +Individual or multiple properties can be updated in a single operation; however, partial updating of nested JSON documents is not supported. This means that all properties of a nested document must be provided in a PUT request for the update of the nested document to be processed, even if the some of the values have not changed. + +## Default properties +At a minimum, each entity is defined by two properties, both of which are strings: type and UUID. The entity 'type' is the singular form of the collection the entity is stored in. For example, an entity in the 'users' collection has an entity type of 'user'. The entity 'UUID' is an immutable universally unique identifier, which can be used to reference the entity. A UUID is automatically generated for every entity when it is created. You can also create custom entities and entity properties; however, Usergrid reserves certain entity types with pre-defined properties by default. For a complete list of reserved entities and properties, see Default Data Entity Types. + +When you access the system via the API, you’ll always provide your organization UUID or name, application UUID or name, and typically the UUID or name of the entity you’re modifying or retrieving. + +All entities have the following default properties: + ++------------+--------+---------------------------------------------------------------------+ +| Property | Type | Description | ++------------+--------+---------------------------------------------------------------------+ +| uuid | UUID | Entity unique id | ++------------+--------+---------------------------------------------------------------------+ +| type | string | entity type (for example, user) | ++------------+--------+---------------------------------------------------------------------+ +| created | long | UTC timestamp in milliseconds of when the entity was created | ++------------+--------+---------------------------------------------------------------------+ +| modified | long | UTC timestamp in milliseconds of when the entity was last modified | ++------------+--------+---------------------------------------------------------------------+ + +Custom entities also have an optional name property that is a string identifier. diff --git a/content/docs/_sources/introduction/overview.txt b/content/docs/_sources/introduction/overview.txt new file mode 100644 index 0000000000..c2a46b4ed4 --- /dev/null +++ b/content/docs/_sources/introduction/overview.txt @@ -0,0 +1,29 @@ +# Getting Started + +The Usergrid documentation is written for a couple of distinctly different audiences. + + +## For Application Developers + +Most of the Usergrid docs are written for you. Browse the left side-bar and work your way down the topics list to learn how to get started using Usergrid for data storage, user management, authentication, push notifications and more. + +* A good place to start is [Using Usergrid](../using-usergrid/creating-account.html) + + +## For Deployment and Operations folks + +If you are the person who will be installing Usergrid, setting up the required Cassandra database, ElasticSearch and other things that Usergrid needs, then you should probably start here: + +* [Usergrid Deployment Guide](../installation/deployment-guide.html) + + +## For Open Source contributoes + +If you want to build Usergrid from source-code then start at our [GitHub repo](http://github.com/apache/usergrid). You will find README files there that explain how to build the Stack, the Portal, SDKs and other components. + +If you want to contribute new code or documentation to the Usergrid project then this is a good place to start: + +* [How to Contribute Code & Docs](../reference/contribute-code.html) + + + diff --git a/content/docs/_sources/introduction/usergrid-features.txt b/content/docs/_sources/introduction/usergrid-features.txt new file mode 100644 index 0000000000..4d73ec299d --- /dev/null +++ b/content/docs/_sources/introduction/usergrid-features.txt @@ -0,0 +1,81 @@ +# Usergrid Features + +Usergrid provides developers with access to a flexible data store and enables you to quickly integrate valuable features into your app, including social graphs, user management, data storage, push notifications, performance monitoring, and more. + +With Usergrid, developers can set up their own cloud-based data platform in minutes instead of months – no server-side coding or back-end development needed. This allows your developers to focus on developing the rich features and user experience that truly differentiate your app, rather than on the time-consuming details of implementing core back-end services and infrastructure. + +## Data storage & management + +### Application data + +At the core of Usergrid is a flexible platform that can store any type of application data, from simple records like a catalog of books to complex associations like user relationships. No matter what type of data drives your app, you can store it as collections of data entities and immediately perform complex queries or full-text searches on any field. You can also create custom entities with custom properties, giving you the ability to store data and context in a way that makes sense for your app. + +To learn more about entities and collections, see [Usergrid Data model](data-model.html). + +For a complete list of the default data entities available, see [Models](../rest-endpoint/api-docs.html#models). + +### Files & assets + +Images, video, and audio are key components of a great app experience. With Usergrid, you can upload and retrieve binary objects from the same data store as the rest of your application data, eliminating the need to set up content delivery networks (CDNs) and easing implementation. We handle all the back-end details that keep your content quickly accessible. + +To learn more about files and asset storage, see [Uploading files and assets](../assets-and-files/uploading-assets.html). + +## Flexible data querying + +One of Usergrid' most powerful features is the ability to perform SQL-style queries and full-text searches on data entities, as well as their properties. This lets you quickly retrieve specific data entities based on multiple criteria, then utilize that data to power social features, target push notifications, perform user analysis, and more. + +Learn more about querying app data, see [Data query overview](../data-queries/querying-your-data.html). + +## Social + +### Entity relationships + +You can create relationships between data entities to help build features, improve user experience, and contextualize data. For example, you might associate a user with their devices to capture valuable geolocation data, create relationships between users to build social graphs, or implement popular features such as activity streams. + +To learn more about entity relationships, see [Entity connections](../entity-connections/connecting-entities.html). + +### Activity streams + +A key aspect of social networking apps is the ability to provide and publish data streams of user actions, such as ongoing lists of comments, activities, and tweets. Usergrid simplifies management and routing of these data streams by providing an activity entity that is specifically designed to automatically create a relationship between activities and the user who created them. + +To learn more about activities and activity feeds, see [Activity feeds](../user-management/activity.html). + +## User management + +### Registration and login + +You can easily add and manage users by providing the core services necessary to handle secure registration and log in, including OAuth 2.0-compliant client authentication. In addition, any number of default or custom data entities and properties can be associated with a user entity to create complete user profiles. + +To learn more about user management, see [User Management](../user-management/user-management.html). + +To learn more about authentication, see Authenticating users and application clients. + +### Roles & permissions + +Applications often require the ability to configure fine-grain control of user access to data, features and functionality. Usergrid solves the implementation details of user access with roles and permissions. Simply create roles that represent user types or access levels, such as Administrator, then assign the necessary permissions to that role. With a single API call, you can then associate your roles with any user or group of users. + +To learn more about user roles and permissions, see [Using Permissions](../security-and-auth/securing-your-app.html). + +### Groups + +Groups are a flexible way to organize your users based on any number of criteria. For example, you might group users based on interests or location to more effectively deliver relevant content, target offers, or customize campaigns. You can also take advantage of the groups entity to enable group-based social networking activities, such as allowing your users to create private information feeds or circles of friends. + +To learn more about groups, see [Working with group data](../user-management/groups.html). + +### Third-party authentication + +In addition to supporting user management and OAuth-based login for your app, Usergrid also makes it easy to integrate third-party authentication through such popular services as Facebook, Twitter and other OAuth-enabled accounts. Providing third-party sign-in can improve user experience, while increasing adoption, giving you access to valuable information from social networks and services. + +To learn more about using third-party sign-in, see [Facebook sign in](../security-and-auth/facebook-sign.html). + +## Geolocation + +The device entity allows you to capture geolocation data from your users' GPS-enabled devices to more effectively target campaigns, push notifications, offers and more. Geolocation also gives you an important data point for contextualizing and analyzing trends and user behavior. + +To learn more about geolocation, see [Geolocation](../geolocation/geolocation.html). + +## Push notifications + +__(Introduced in Usergrid 2)__ Push notifications are the most effective way to engage your users with relevant content, and thanks to Usergrid, implementing them can be done in minutes. Simply register your app and your user's devices with a notification provider, such as Apple Push Notification Service or Google Cloud Messaging, then use the Usergrid notification entity to send millions of push notifications a month at no cost. When used in conjunction with queries of user and application data, push notifications become a powerful tool for leveraging user data, ensuring relevancy and driving engagement. + +To learn more about push notifications, see [Push notifications overview](../push-notifications/tbd.html). diff --git a/content/docs/_sources/jersey2skeleton/README.txt b/content/docs/_sources/jersey2skeleton/README.txt new file mode 100644 index 0000000000..f0115f195e --- /dev/null +++ b/content/docs/_sources/jersey2skeleton/README.txt @@ -0,0 +1,9 @@ +# jersey2skeleton + +This is a minimal example project designed to mimic how Usergrid uses Jersey 2. + +Goal is to determine correct way to use Jersey and Swagger annotations to automatically +generate Swagger from Usergrid's Java code. + +Current status: cannot determine correct combination of annotations to get the correct +Swagger generated for the /management and /management/organizations end-points. diff --git a/content/docs/_sources/orgs-and-apps/admin-user.txt b/content/docs/_sources/orgs-and-apps/admin-user.txt new file mode 100644 index 0000000000..6b1b7d3d78 --- /dev/null +++ b/content/docs/_sources/orgs-and-apps/admin-user.txt @@ -0,0 +1,352 @@ +# Admin user +An admin user has full access to perform any operation on all organization accounts of which the admin user is a member. Using the API Services BaaS API, you can create, update, or retrieve an admin user. You can also set or reset an admin user's password, activite or reactivate an admin user, and get an admin user's activity feed. + +In addition, you can add, retrieve, or remove an admin user from an organization. For information on these organization-related operations, see [Organization](organization.html). + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security_and_auth/authenticating-users-and-application-clients.html) for details. + +## Creating an admin user +Use the POST method to create an admin user. + +### Request URI + + POST /management/organizations/{org}/users {request body} + +In the request body send a JSON object that represents the new user, for example: + + { + "username" : "jim.admin", + "email" : "jim.admin@gmail.com", + "name" : "Jim Admin", + "password" : "test12345" + } + + +### Example - Request + + curl -X -i POST "https://api.usergrid.com/management/organizations/my-org/users" -d '{"username":"jim.admin","name":"Jim Admin","email":"jim.admin@gmail.com","password":"test12345"}' + +### Example - Response + + { + "action": "post", + "status": "ok", + "data": { + "user": { + "applicationId": "00000000-0000-0000-0000-000000000001", + "username": "jim.admin", + "name": "Jim Admin", + "email": "jim.admin@gmail.com", + "activated": true, + "disabled": false, + "uuid": "335b527f-cd0d-11e1-bef8-12331d1c5591", + "adminUser": true, + "displayEmailAddress": "jim.admin ", + "htmldisplayEmailAddress": "jim.admin jinm.admin@gmail.com" + } + }, + "timestamp": 1349390189106, + "duration": 11808 + } + + +## Updating an admin user +Use the PUT method to update an admin user. + +### Request URI + + PUT /management/organizations/{org}/users/{user|username|email|uuid} {request body} + +Parameters + +Parameter Description +--------- ----------- +User identifier Username, name, email address, or UUID. +request body JSON object containing propties you would like to add/update on user. + +For example, to add city and state to user, send this: + + { + "city" : "San Francisco", + "state" : "California" + } + +### Example - Request + + curl -X -i PUT "https://api.usergrid.com/management/organizations/my-org/users/jim.admin" -d '{"city":"San Francisco","state":"California"}' + +### Example - Response + + { + "action": "update user info", + "timestamp": 1349479321874, + "duration": 0 + } + +## Getting an admin user +Use the GET method to retrieve details about an admin user. + +### Request URI + + GET /management/organizations/{org}/users/{user|username|email|uuid} + +Parameters + +Parameter Description +--------- ----------- +User identifier Admin username, name, email address, or UUID. + + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/organizations/my-org/users/jim.admin" + +### Example - Response + + { + "action": "get admin user", + "status": "ok", + "data": { + "username": "jim.admin", + "token": "YWMt4NqE8Q9GEeLYJhIxPSiO4AAAATo5fQfcG0cEd2h9nwmDmRorkNNrEeQyDOF", + "email": "edort1@gmail.com", + "organizations": { + "jim.admin": { + "users": { + "jim.admin": { + "applicationId": "00000000-0000-0000-0000-000000000001", + "username": "jim.admin", + "name": "Jim Admin", + "email": "jim.admin@gmail.com", + "activated": true, + "disabled": false, + "uuid": "328b526e-cd0c-11e1-bcf8-12424d1c4491", + "adminUser": true, + "displayEmailAddress": "jim.admin ", + "htmldisplayEmailAddress": "jim.admin <jim.admin@gmail.com>" + }, + ... + "adminUser": true, + "activated": true, + "name": "edort1", + "applicationId": "00000000-0000-0000-0000-000000000001", + "uuid": "328b526e-cd0c-11e1-bcf8-12424d1c4491", + "htmldisplayEmailAddress": "jim.admin <jim.admin@gmail.com>>", + "displayEmailAddress": "jim.admin ", + "disabled": false + }, + "timestamp": 1349480786906 + } + +## Setting an admin user's password +Use the PUT method to update an admin user's password. + +### Request URI + + PUT /management/users/{user|username|email|uuid}/password {request body} + +Parameters + +Parameter Description +--------- ----------- +User identifier Admin username, name, email address, or UUID. + +Expects new and old password to be sent in request body: + + { + "password": + "newpassword": + } + +### Example - Request + + curl -X -i PUT "https://api.usergrid.com/management/users/jim.admin/password" -d '{"oldpassword":"test123", "newpassword":"mynewpassword"}' + +### Example - Response + + { + "action": "set user password", + "timestamp": 1349714010142, + "duration": 0 + } + +## Resetting an admin user's password +Resetting an admin user's password is a two step process. In the first step, you initiate the password reset. This returns a browser page. The page includes a field for the user to enter his or her email address, and a field to enter a response to a Captcha challenge. In the second step, you handle the user's responses from the form. + +### Initiating a password reset +Use the GET method to initiate the password reset. + +### Request URI + + GET /management/organizations/{org}/users/resetpw + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/organizations/my-org/users/resetpw" + +### Example - Response + + + + + + Reset Password + + + + + +
+
Incorrect Captcha, try again...
+
+
+

+ +

+

+ +

+

+ + +

+ +

+
+
+
+ + +## Completing a password reset +Use the POST method to complete the password reset. + +### Request URI + + POST /management/organizations/{org}/users/resetpw {request body} + +In the request body send parameters and value for the Captcha challenge, the admin user's response to the Captcha challenge, and the admin user's email address, for example: + + { + "recaptcha_response_field" : "Atistophanes tseFia", + "recaptcha_challenge_field" : "Atistophanes tseFia", + "email" : "jim.admin@gmail.com" + } + +### Example - Request + + curl -X -i POST "https://api.usergrid.com/management/organizations/my-org/users/resetpw" -d '{"recaptcha_response_field":"Atistophanes tseFia","recaptcha_challenge_field":"Atistophanes tseFia","email":"jim.admin@gmail.com"}' + +### Example - Response + + { + "action": "reset user password", + "timestamp": 13546154010321, + "duration": 0 + } + +## Activating an admin user +Use the GET method to activate an admin user from a link provided in an email notification. + +### Request URI + + GET /management/organizations/{org}/users/{user|username|email|uuid}/activate?token={token}&confirm={confirm_email} + +Parameters + +Parameter Description +--------- ----------- +User identifier Admin username, name, email address, or UUID. +string token Activation token (supplied via email). +confirm_email Send confirmation email (false is the default). + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/organizations/my-org/users/jim.admin/activate?token=33dd0563-cd0c-11e1-bcf7-12313d1c4491" + +### Example - Response + + { + "action": "activate user", + "timestamp": 1349718021324, + "duration": 0 + } + +## Reactivating an admin user +Use the GET method to reactivate an admin user. + +### Request URI + + GET /management/organizations/{org}/users/{user|username|email|uuid}/reactivate + +Parameters + +Parameter Description +--------- ----------- +User identifier Admin username, name, email address, or UUID. + +## Example - Request + + curl -X GET "https://api.usergrid.com/management/organizations/my-org/users/jim.admin/reactivate" + +### Example - Response + + { + "action": "reactivate user", + "timestamp": 1349735217217, + "duration": 3541 + } + +## Getting an admin user's activity feed +Use the GET method to retrieve an admin user's activity feed. + +### Request URI + + GET /management/organizations/{org}/users/{user|username|email|uuid}/feed + +Parameters + +Parameter Description +--------- ----------- +User identifier Admin username, name, email address, or UUID. + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/organizations/my-org/users/jim.admin/feed" + +### Example - Response + + { + "action": "get admin user feed", + "status": "ok", + "entities": [ + { + "uuid": "cf3e981c-fe80-11e1-95c8-12331b144c65", + "type": "activity", + "created": 1347643370454, + "modified": 1347643370454, + "actor": { + "displayName": "jim.admin", + "objectType": "person", + "uuid": "335b527f-cd0d-11e1-bef8-12331d1c5591", + "entityType": "user" + }, + "category": "admin", + "metadata": { + "cursor": "gGkAAQMAgGkABgE5xc3r1gCAdQAQz02YHP6QEeGVyBIxOxIsVgCAdQAQz4ZbYf6QEeGVyBIxOxIsVgA", + "path": "/users/327b527f-cd0c-11e1-bcf7-12313d1c4491/feed/cf4d981c-fe90-11e1-95c8-12313b122c56" + }, + "object": { + ... + }, + "published": 1342198809251, + "title": "
jim.admin (jim.admin@gmail.com) created a new organization account named jim.admin", + "verb": "create" + } + ], + "timestamp": 1349735719320, + } diff --git a/content/docs/_sources/orgs-and-apps/application.txt b/content/docs/_sources/orgs-and-apps/application.txt new file mode 100644 index 0000000000..801b9ef2ab --- /dev/null +++ b/content/docs/_sources/orgs-and-apps/application.txt @@ -0,0 +1,100 @@ +# Application +You can create a new application in an organization through the Admin portal. The Admin portal creates the new application by issuing a post against the management endpoint (see the [Creating an Application](../orgs-and-apps/application.html#creating-an-application) section in Organization for details). If you need to create an application programmatically in your app, you can also use the API to do this. You can access application entities using your app name or UUID, prefixed with the organization name or UUID: + + https://api.usergrid.com/{org_name|uuid}/{app_name|uuid} + +Most mobile apps never access the application entity directly. For example you might have a server-side web app that accesses the application entity for configuration purposes. If you want to access your application entity programmatically, you can use the API. + +## Creating an application +To create an application you POST a JSON object containing (at a minimum) the name of the new application. +You will also need to pass authentication credentials. + +### Request URI + + POST /management/organizations|orgs/{org_name}|{org_uuid}/apps {request body} + +Parameters + +Parameter Sent in Description +--------- ------- ----------- +grant_type Query string Only the value 'client_credentials' is supported. +client_id Query string The org-level client id for your org, found in the 'Org Administration' menu of Usergrid portal. +client_secret Query string The org-level client secret for your org, found in the 'Org Administration' menu Usergrid portal. +name Request Body The name of the application. + +### Example - Request + + curl -X -i POST "https://api.usergrid.com/management/orgs/testorg/apps?grant_type=client_credentials&client_id=b3U68vghI6FmEeKn9wLoGtzz0A&client_secret=b3U6ZuZ5_U8Y-bOaViJt0OyRkJFES-A" -d '{"name":"testapp1"}' + +### Example - Response + + { + "action": "new application for organization", + "timestamp": 1338914698135, + "duration": 701 + } + +## Generating application credentials +Use the POST method to generate the client ID and client secret credentials for an application in an organization. + +### Request URI + + POST /organizations|orgs/{org_name}|{uuid}/applications|apps/{app_name}|{uuid}/credentials + +Parameters + +Parameter Description +--------- ----------- +string org_name|arg uuid Organization name or organization UUID. +string app_name|arg uuid Application name or application UUID. + +Note: You also need to provide a valid access token with the API call. See [Authenticating users and application clients](../security_and_auth/authenticating-users-and-application-clients.html) for details. + +### Example - Request + + curl -X POST "https://api.usergrid.com/management/orgs/testorg/apps/testapp1/credentials" + +### Example - Response + + { + "action": "generate application client credentials", + "timestamp": 1349815979529, + "duration": 535, + "credentials": { + "client_id": "YXA7ygil-f3TEeG-yhIxPQK1cQ", + "client_secret": "YXA65gYlqja8aYYSAy8Ox3Vg5aRZp48" + } + } + +## Getting application credentials +Use the GET method to retrieve the client ID and client secret credentials for an application in an organization. + +### Request URI + + GET /organizations|orgs/{org_name}|{uuid}/applications|apps/{app_name}|{uuid}/credentials + +Parameters + +Parameter Description +--------- ----------- +string org_name|arg uuid Organization name or organization UUID. +string app_name|arg uuid Application name or application UUID. + +Note: You also need to provide a valid access token with the API call. See [Authenticating users and application clients](../security_and_auth/authenticating-users-and-application-clients.html) for details. + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/orgs/testorg/apps/testapp1/credentials" + +### Example - Response + + { + "action": "get application client credentials", + "timestamp": 1349816819545, + "duration": 7, + "credentials": { + "client_id": "YXA7ygil-f3TEeG-yhIxPQK1cQ", + "client_secret": "YXA65gYlqja8aYYSAy8Ox3Vg5aRZp48" + } + } + diff --git a/content/docs/_sources/orgs-and-apps/managing.txt b/content/docs/_sources/orgs-and-apps/managing.txt new file mode 100644 index 0000000000..3c0980756a --- /dev/null +++ b/content/docs/_sources/orgs-and-apps/managing.txt @@ -0,0 +1,50 @@ +# Organization & application management +Your application can use the App Services API to request a variety of management operations on App Services resources. For example, your application can request an access token to use in operations on entities and collections. Or it can create an organization to contain the applications, entities, and collections for a company, team, or project. + +Your application makes requests through the API using HTTP methods such as GET, POST, PUT, and DELETE, and specifies the pertinent resource URL. For management operations, the URL begins with ``/management/``. See [Using the API](../getting-started/using-the-api.html) for general usage information, such as how to construct an API request. + +The following table lists and describes resources accessible through the App Services API on which your application can perform management operations. Click on a resource for further details about the resource and its methods. + + + + + + + + + + + + + + + + + + + + + + +
+ Resource + + Description +
+ [Access Token](../security-and-auth/authenticating-users-and-application-clients.html) + + Carries the credentials and authorization information needed to access other resources through the Usergrid API. +
+ [Client Authorization](../security-and-auth/authenticating-api-requests.html) + + Authorizes the client. +
+ [Organization](organization.html) + + The highest level structure in the Usergrid data hierarchy. +
+ [Admin User](adminuser.html) + + A user that has full access to perform any operation on all organization accounts of which the user is a member. +
+ diff --git a/content/docs/_sources/orgs-and-apps/organization.txt b/content/docs/_sources/orgs-and-apps/organization.txt new file mode 100644 index 0000000000..3980ae906a --- /dev/null +++ b/content/docs/_sources/orgs-and-apps/organization.txt @@ -0,0 +1,435 @@ +# Organization + +An organization represents the highest level of the API Services BaaS data hierarchy. It contains applications (and the entities and collections they contain) and is associated with one or more administrators. An organization can be representative of a company, team, or project. It allows multiple applications to be shared within the organization with other administrators. + +## Creating an organization +Use the POST method to create an organization through a form post. + +### Request URI + + POST /organizations|orgs {request body} + +Parameters + +Expected to be sent form data in the body of the request. + +Parameter Description +--------- ----------- +organization (string) The name of the organization. +username (string) The username of the administrator. +name (string) The name of the administrator. +email (string) The email address of the administrator. +password (string) The password of the administrator. + + +### Example - Request + + curl -X -i POST "https://api.usergrid.com/management/orgs" -d '{"password":"test12345","email":"tester123@hotmail.com","name":"test","username":"test123","organization":"testorg"}' + +### Example - Response + + { + "action": "new organization", + "status": "ok", + "data": { + "owner": { + "applicationId": "00000000-0000-0000-0000-000000000001", + "username": "tester123", + "name": "test", + "email": "tester123@hotmail.com", + "activated": false, + "disabled": false, + "uuid": "48c92c73-0d7e-11e2-98b9-12313d288ee0", + "adminUser": true, + "displayEmailAddress": "tester123 ", + "htmldisplayEmailAddress": "tester123 <tester123@hotmail.com>" + }, + "organization": { + "name": "testorg", + "uuid": "5de0bb69-0d7f-11e2-87b9-12313d288ff0" + } + }, + "timestamp": 1349284674173, + "duration": 21376 + } + +## Getting an organization +Use the GET method to retrieve an organization given a specified UUID or username. + +### Request URI + + GET /organizations|orgs/{org_name}|{uuid} + +Parameters + +Parameter Description +--------- ----------- +org_name|arg uuid Organization name or organization UUID. + +Note: You also need to provide a valid access token with the API call. +See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/orgs/testorg" + +### Example - Response + + { + "timestamp": 1349286861746, + "duration": 18, + "organization": { + "users": { + "tester123": { + "applicationId": "00000000-0000-0000-0000-000000000001", + "username": "tester123", + "name": "test", + "email": "tester123@hotmail.com", + "activated": true, + "disabled": false, + "uuid": "327b527f-cd0c-11e1-bcf7-12313d1c4491", + "adminUser": true, + "displayEmailAddress": "tester123 ", + "htmldisplayEmailAddress": "tester123 <tester123@hotmail.com>" + } + }, + "name": "testorg", + "applications": { + "tester123/sandbox": "3400ba10-cd0c-11e1-bcf7-12313d1c4491", + "tester123/testapp1": "be08a5f9-fdd3-11e1-beca-12313d027471", + "tester123/testapp2": "cede5b7e-fe90-11e1-95c8-12313b122c56" + }, + "uuid": "33dd0563-cd0c-11e1-bcf7-12313d1c4491" + } + +## Activating an organization +Use the GET method to activate an organization from a link provided in an email notification. + +### Request URL + + GET /organizations|orgs/{org_name}|{uuid}/activate?token={token}&confirm={confirm_email} + +Parameters + +Parameter Description +--------- ----------- +org_name|arg uuid Organization name or organization UUID. +token Activation token (supplied via email). +confirm_email (boolean) Send confirmation email (false is the default). + + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/orgs/testorg/activate?token=33dd0563-cd0c-11e1-bcf7-12313d1c4491" + +### Example - Response + + { + "action": "activate organization", + "timestamp": 1337928462810, + "duration": 3342 + } + +## Reactivating an organization +Use the GET method to reactivate an organization. + +### Request URI + + GET /organizations|orgs/{org_name}|{uuid}/reactivate + +Parameters + +Parameter Description +--------- ----------- +string org_name|arg uuid Organization name or organization UUID. + + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/orgs/testorg/reactivate" + +### Example - Response + + { + "action": "reactivate organization", + "timestamp": 1349385280891, + "duration": 3612 + } + +## Generating organization client credentials +Use the POST method to generate new credentials for an organization client. + +### Request URI + + POST /organizations|orgs/{org_name}|{uuid}/credentials + +Parameters + +Parameter Description +--------- ----------- +string org_name|arg uuid Organization name or organization UUID. + +__Note__: You also need to provide a valid access token with the API call. [Authenticating users and application clients](../security_and_auth/authenticating-users-and-application-clients.html) for details. + +### Example - Request + + curl -X POST "https://api.usergrid.com/management/orgs/credentials" + +### Example - Response + + { + "action": "generate organization client credentials", + "timestamp": 1349385795647, + "duration": 7, + "credentials": { + "client_id": "c2V7N61DY90MCdG78xIxPRxFdQ", + "client_secret": "c2V7WEdXIutZWEkWdySLCt_lYDFVMMN" + } + } + +## Retrieving organization client credentials +Use the GET method to retrieve the credentials for an organization client. + +### Request URL + + GET /organizations|orgs/{org_name}|{uuid}/credentials + +Parameters + +Parameter Description +--------- ----------- +string org_name|arg uuid Organization name or organization UUID. + +__Note__: You also need to provide a valid access token with the API call. See [Authenticating users and application clients](../security_and_auth/authenticating-users-and-application-clients.html) for details. + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/orgs/testorg/credentials" + +### Example - Response + + { + "action": "get organization client credentials", + "timestamp": 1349386672984, + "duration": 690, + "credentials": { + "client_id": "c2V7N61DY90MCdG78xIxPRxFdQ", + "client_secret": "c2V7WEdXIutZWEkWdySLCt_lYDFVMMN" + } + } + +## Getting an organization's activity feed +Use the GET method to get an organization's activity feed. + +### Request URI + + GET /organizations|orgs/{org_name}|{uuid}/feed + +Parameters + +Parameter Description +--------- ----------- +string org_name|arg uuid Organization name or organization UUID. + +__Note__: You also need to provide a valid access token with the API call. See [Authenticating users and application clients](../security_and_auth/authenticating-users-and-application-clients.html) for details. + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/orgs/testorg/feed" + +### Example - Response + + { + { + "action": "get organization feed", + "status": "ok", + "entities": [ + { + "uuid": "cf4d981c-fe90-11e1-95c8-12313b122c56", + "type": "activity", + "created": 1347643370454, + "modified": 1347643370454, + "actor": { + "displayName": "tester123", + "objectType": "person", + "uuid": "327b527f-cd0c-11e1-bcf7-12313d1c4491", + "entityType": "user" + }, + "category": "admin", + "metadata": { + "cursor": "gGkAAQMAgGkABgE5xc3r1gCAdQAQz02YHP6QEeGVyBIxOxIsVgCAdQAQz3SoH_6QEeGVyBIxOxIsVgA", + "path": "/groups/33dd0563-cd0c-11e1-bcf7-12313d1c4491/feed/cf4d981c-fe90-11e1-95c8-12313b122c56" + }, + "object": { + "displayName": "testapp2", + "objectType": "Application", + "uuid": "cede5b7e-fe90-11e1-95c8-12313b122c56", + "entityType": "application_info" + }, + "published": 1347643370454, + "title": "tester123 (tester123@hotmail.com) created a new application named testapp2", + "verb": "create" + },... + , + "timestamp": 1349387253811 + } + +## Getting the applications in an organization +Use the GET method to retrieve the applications in an organization. + +### Request URI + + GET /organizations|orgs/{org_name}|{uuid}/applications|apps + +Parameters + +Parameter Description +--------- ----------- +string org_name|arg uuid Organization name or organization UUID. + +__Note__: You also need to provide a valid access token with the API call. See [Authenticating users and application clients](../security_and_auth/authenticating-users-and-application-clients.html) for details. + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/orgs/testorg/apps" + +### Example - Response + + { + "action": "get organization application", + "data": { + "testorg/sandbox": "3500ba10-cd0c-11e1-bcf8-12313d1c5591", + "testorg/testapp1": "be09a5f9-fdd3-11e1-beca-12313d027361", + "testorg/testapp2": "cede5b8e-fe90-11e1-65c8-12313b111c56" + }, + "timestamp": 1349815338635, + "duration": 22 + } + +## Adding an admin user to an organization +Use the PUT method to add an existing admin user to an organization. + +### Request URI + + PUT /organizations|orgs/{org_name}|{org_uuid}/users/{username|email|uuid} + +Parameters + +Parameter Description +--------- ----------- +string org_name|arg org_uuid Organization name or organization UUID. +string username|string email|arg uuid User name, user email address, or user UUID. + + +### Example - Request + + curl -X PUT "https://api.usergrid.com/management/orgs/testorg/users/test123" + +### Example - Response + + { + "action": "add user to organization", + "status": "ok", + "data": { + "user": { + "applicationId": "00000000-0000-0000-0000-000000000001", + "username": "tester123", + "name": "test", + "email": "tester123@hotmail.com", + "activated": true, + "disabled": false, + "uuid": "335b527f-cd0d-11e1-bef8-12331d1c5591", + "adminUser": true, + "displayEmailAddress": "tester123 ", + "htmldisplayEmailAddress": "tester123 <tester123@hotmail.com>" + } + }, + "timestamp": 1349390189106, + "duration": 11808 + } + +## Getting the admin users in an organization + +Use the GET method to retrieve details about the admin users in an organization. + +### Request URI + + GET /organizations|orgs/{org_name}|{org_uuid}/users + +Parameters + +Parameter Description +--------- ----------- +org_name|arg org_uuid Organization name or organization UUID. + +### Example - Request + + curl -X GET "https://api.usergrid.com/management/orgs/testorg/users" + +### Example - Response + + { + "action": "get organization users", + "data": { + "user": { + "applicationId": "00000000-0000-0000-0000-000000000001", + "username": "tester123", + "name": "test", + "email": "tester123@hotmail.com", + "activated": true, + "disabled": false, + "uuid": "335b527f-cd0d-11e1-bef8-12331d1c5591", + "adminUser": true, + "displayEmailAddress": "tester123 ", + "htmldisplayEmailAddress": "tester123 <tester123@hotmail.com>" + } + }, + "timestamp": 13494542201685, + "duration": 10 + } + +## Removing an admin user from an organization + +Use the DELETE method to remove an admin user from an organization. All organizations must have a minimum +of one user with org admin privileges. If you attempt to delete the last org admin in an organization, +the API will return a 400 Bad Request error. + +### Request URI + + DELETE /organizations|orgs/{org_name}|{org_uuid}/users/{username|email|uuid} + +Parameters + +Parameter Description +--------- ----------- +org_name|arg org_uuid Organization name or organization UUID. +username|string email|arg uuid User name, user email address, or user UUID. + +### Example - Request + + curl -X DELETE "https://api.usergrid.com/management/orgs/testorg/users/test123" + +### Example - Response + + { + "action": "remove user from organization", + "status": "ok", + "data": { + "user": { + "applicationId": "00000000-0000-0000-0000-000000000001", + "username": "tester123", + "name": "test", + "email": "tester123@hotmail.com", + "activated": true, + "disabled": false, + "uuid": "335b527f-cd0d-11e1-bef8-12331d1c5591", + "adminUser": true, + "displayEmailAddress": "tester123 ", + "htmldisplayEmailAddress": "tester123 <tester123@hotmail.com>" + } + }, + "timestamp": 1349453590005, + "duration": 727 + } + + \ No newline at end of file diff --git a/content/docs/_sources/push-notifications/adding-push-support.txt b/content/docs/_sources/push-notifications/adding-push-support.txt new file mode 100644 index 0000000000..956ac8621f --- /dev/null +++ b/content/docs/_sources/push-notifications/adding-push-support.txt @@ -0,0 +1,158 @@ +# Adding push notifications support +You add push notification support by configuring services, then adding app code to receive messages. You'll set up an account with a notification service (such as Apple's APNs or Google's GCM). Then you'll configure your App Services application to send notifications to the service. Then you'll add code to receive messages. + +## Setting up push notification support +The following steps get you set up so that your app can receive push notifications. Keep in mind that these steps build on one another. In other words, you'll need values generated in step 1 in order to complete step 2, and so on. + +For a walkthrough of these steps using a push sample app, see [Tutorial: Push notifications sample app]. + +1. __Register your app__ with push notification services. +Your notification messages will be forwarded to devices by Apple and/or Google. So you'll need to register with Apple APNs and/or Google's GCM. For more information, see Registering with a notification service. + +2. __Create a notifier__ to send notification messages from App Services to notification services. +App Services will use your notifier to send your messages to a notification service. For details, see Creating notifiers. To create a notifier, you'll need information generated by registering with a push notification service. You'll need a separate notifier for each app/platform combination. + +3. __Register devices__ at run time. +At run time, your code will register to receive notifications. To do this, your code uses information from the notification service and App Services notifier. For more, see Managing users and devices. + +4. __Send and manage push notifications__ +You use App Service API notification endpoints to target devices, users, or groups with your messages. To learn more, see Creating and managing notifications. + +### How the pieces connect +Click a tab below to view more information about how the pieces connect once you've got it set up. + +### Apple APNs + +The diagram below illustrates what things should look like once you've gotten set up to send notifications that are received by your app. + +A. At configuration time, you create an App ID, then create an App Services notifier with a .p12 certificate you generate on your Mac. The .p12 certificate correlates the notifier (which you will use to send notification messages from App Services) with the App ID (so that APNs will forward your notifications to devices). + +B. A run time, your app's code registers with Apple for notifications by invoking the registerForRemoteNotificationTypes method to receive a token it can send to App Services. + +C. At run time, your app's code registers with App Services for notifications by sending the name of the App Services notifier you created. This ensure's that there's a device entity in your App Service application. That way, you can address the device with notification messages. + +For information on troubleshooting push notifications on iOS devices, see Troubleshooting Push Notifications + +### Google GCM + +Google GCM +The diagram below illustrates what things should look like once you've gotten set up to send notifications that are received by your app. + +A. At configuration time, you create a Google API project, then create an App Services notifier with an API key from the project. The API key correlates the notifier (which you will use to send notification messages from App Services) with the API project (which will forward your notifications to devices). + +B. At run time, your app's code registers with App Services for notifications by sending the name of the App Services notifier you created. This ensure's that there's a device entity in your App Service application. That way, you can address the device with notification messages. + +C. A run time, your app's code registers with Google for notifications by sending the number of your API project as a "sender ID". The project is the actual notification "sender" that will forward notifications to your app. In other words, the app is telling Google that it wants to receive notifications from that sender. + + + +## Requirements +Before you start adding support for push notifications, be sure you've got the following: + +An Apigee account (it’s free). If you don't yet have an Apigee account, you can create one. +An App Services organization. Organizations are top-level containers for your APIs and other resources. By default, your Apigee account will include one organization that has the same name as your username. You can view your current organizations or create a new one by visiting your account dashboard. +An App Services application. An App Services application is where you store you App Services data and where you schedule notifications. Data in the application represents devices, notifiers, notifications, users, and groups. For information on creating an app, see Registering apps. +You will need to test with a mobile device running the platform you're developer for. In the case of Android, you might be able to use an emulator. It is not possible to test push notifications from a web browser. + +### iOS +To develop push notifications for an iOS app, you'll need: + +A Mac to generate the necessary SSL certificate. +An iOS developer account. You'll need this to register for an App ID and get a provisioning profile. To get an account, visit the iOS Dev Center. +An actual iOS device to test push notifications. It's not yet possible to develop push notifications with an emulator. +An iOS provisioning profile +For iOS app testing, you need a provisioning profile that's associated with an Apple ID. You set up the provisioning profile in the Apple developer portal, download the profile, and import it into Xcode. + +To set up a provisioning profile, you need to create an "iOS App Development" certificate in the Apple developer portal. For example, in the Apple APNs setup earlier in this tutorial, you created a certificate in the Apple developer portal to be used for push notifications. However, you won't be able to create a provisioning portal with just that certificate. You also need to create an "iOS App Development" certificate (the configuration settings don't matter), as shown in the following image. + +ios dev certificate + +After you create an iOS App Development certificate, you can create a provisioning profile that includes your App ID/certificate for push notifications. + +### Android + +It's generally a best practice to develop Android apps by testing and debugging with an Android device. It's also possible to use an emulator. + +Before testing and debugging with an Android device, you'll need to set up your device for development. Be sure to see the Android documentation on using hardware devices. + +To test with an emulator, you will need to follow these steps: + +Ensure that you have Google API 8 (or above) and Android 2.2 (or above). +Using the Android SDK Manager, install Google Cloud Messaging for Android Library. +Using the Android Virtual Device Manager, create an emulator whose target is Google APIs. +Ensure that the emulator you're using includes a Google account. +Launch the emulator. +In the emulator, click the Menu button, then go to Settings > Accounts & Sync. +Add a Google account. +Once you've finished these steps, you should have an emulator that can receive push notification messages. + +### PhoneGap + +You'll need to test with a device or emulator. It is not possible to test push notifications with a browser alone. +PhoneGap Push plug-in. Developers using PhoneGap to develop their apps with HTML5 and Javascript will need to install the Apigee push notification PhoneGap plug-in to enable push notifications. Installation instructions are available in the plug-in Readme.md file, as well as in Tutorial: Push notifications sample app. The plug-in is already included in the above PhoneGap sample apps. + +## Tutorials +Written tutorial +For a full step-by-step tutorial using iOS, Android, or JavaScript, see Tutorial: Push notifications sample app. + +Video tutorial +Click the tab for your preferred development platform to watch a full walkthrough video about how to integrate the App Services push notifications feature into your app. + +### iOS + +### Android + +## Sample Apps + +You'll find samples in SDKs that are specific to three mobile platforms: iOS, Android, and JavaScript. These show a simple implementation of push notifications in action. After you perform a few setup steps, running the sample app on your connected device or emulator, you will be able to send a push notification to it by clicking a button in the app's UI. You will also be able to send more pushes to it from the App Services console. + +To download the sample app and view the tutorial, see Tutorial: Push notifications sample app. + +When you create notifiers to run the samples, creating them in the default "sandbox" app in your Usergrid organization will make it easier to try out the feature. The sandbox app doesn't require authentication. + +## Troubleshooting + +### Android / PhoneGap + +App fails to install on the emulator +When using the emulator, be sure to note the setup steps in the requirements section. + +Sometimes installation fails while the emulator is still being launched. Wait until the emulator is up and running (so that you can unlock and interact with the UI), then run the project again. + +Make sure that the order of your Java Build Path matches the order shown in Tutorial: Push notifications sample app. + +#### Push errors +If pressing the button to send yourself a push throws an exception or doesn't respond: + +Make sure the emulator's target matches the Google API version used in the project. + +In the IDE log, wait until you see that the device has been registered before sending yourself a push. +Sometimes waiting for the code to run and trying another click gets the push message to you. + +If you successfully send yourself a push message once but fail to again, try one of the following: + +Go to the apps list on the device and launch the app from there. + +Uninstall the app from the device, delete the device in the App Services console, and run the project again. + +#### MismatchSenderId error message from the server when it tries to send a message to your app. + +The sender ID is a number you send to GCM from app code when registering with GCM for notifications. The error might be occurring because the sender ID with which your app is registering at GCM for notifications does not correlate to the API project whose API key was used to create your App Services notifier. First, confirm the following: + +* The sender ID in your app code (used when registering with GCM) is the same as your Goole API project number. + +* The API key used to create your App Services notifier is the same as the API key in your Google API project. + +* The notifier name used in your app code is the same as for the notifier you created in App Services. + +It can be possible to make a fix (such as by correcting the sender ID in your app code) and still see this error. If you're still seeing the error, consider create a new API project and App Services notifier, then use their new values in your code: + +1. Recreate (or create anew) the Google API project. This will generate a new API key and project number. See Registering with a notification service. + +2. Create a new App Services notifier for GCM using the API key you generated with the new API project. See Creating notifiers. + +3. Use the new notifier name in your code, along with a new sender ID that is that same value as the Google API project number. + +#### INVALID_SENDER error message + +The sender ID is a number you send to GCM from app code when registering with GCM for notifications. The "sender" in this case is the Google API project you created to send notification messages. Confirm that the sender ID you're using in code is the same value as the API project number generated when you created your Google API project. See Registering with a notification service. \ No newline at end of file diff --git a/content/docs/_sources/push-notifications/creating-and-managing-notifications.txt b/content/docs/_sources/push-notifications/creating-and-managing-notifications.txt new file mode 100644 index 0000000000..501dbee91d --- /dev/null +++ b/content/docs/_sources/push-notifications/creating-and-managing-notifications.txt @@ -0,0 +1,271 @@ +# Creating and managing notifications +This topic provides information on setting up and sending push notifications with the Usergrid API backend as a service (BaaS). For high-level information, prerequisites, and tutorials, see [Push notifications overview](overview.html). + +

Note


 +Although not shown in many of the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. +

+ +

Note


 +For an overview of how to set up push notifications, including troubleshooting tips, see [Adding push notifications support](adding-push-support.html). +

+ +## Creating notifications +When you create a notification, it is scheduled to be delivered to all applicable devices immediately unless the deliver property has been set. A notification may contain multiple messages (payloads), and each payload must be associated with a notifier in order to deliver that message to the associated app. This allows a single notification to be delivered to multiple apps across various services, and is useful if you want to send messages to multiple notifiers, such as development and production versions of both Apple and Google simultaneously. + +Notification can be created via POST request to the BaaS API, or in the admin portal: + +### Creating notificastions with cURL + +#### Targeting a single device +This request will target a specific device entity. + +Request Syntax + + curl -X POST https://api.usergrid.com///devices//notifications -d '{"payloads":{:}}' + +#### Targeting all devices +This request will target all device entities. + +Request Syntax + + curl -X POST https://api.usergrid.com///devices/*/notifications -d '{"payloads":{:}}' + +#### Targeting a single user +This request will target a specific user entity. + +Request Syntax + + curl -X POST https://api.usergrid.com///users//notifications -d '{"payloads":{:}}' + +#### Targeting a group +This request will target all users associated with a specific group entity. + +Request Syntax + + curl -X POST https://api.usergrid.com///groups//notifications -d '{"payloads":{:}}' + +#### Targeting users by location +This request will target all device entities that are within a set radius of a latitude/longitude coordinate. + +Request Syntax + + curl -X POST https://api.usergrid.com///devices;ql=location within of ,/notifications -d '{"payloads":{:}}' + +#### Request Parameters + +The following parameters can be specified when targeting push notifications. + +Base URL + +These parameters are used in forming the base URL of the request: + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name + +Notification + +These parameters are used when forming the notification portion of the request: + +Parameter Description +--------- ----------- +notifier The ``notifier`` entity you wish to associate with the notification (see [Creating notifiers](creating-notifiers.html) for information on creating notifiers) +message The push notification message that will be delivered to the user + +__Note__: If your message contains double-quotes ("") you must escape them with a backslash + +Targets + +These parameters are used when specifying the notification target in the request. + +Parameter Description +--------- ----------- +device UUID of a device entity. +user UUID or username of a user entity. +phone_type Specified in a appended query string. The type property of a device entity. +group UUID or name of the group entity. +latitude, longitude, radius Specified in a appended query string. The radius in meters of a user device from a latitude/longitude coordinate. + + +### Creating notificastions with Admin portal + +To create the new notification with the admin portal, do the following: + +1. Log in to the admin portal. +2. In the left nav, click __Push > Send Notification__. +3. From the __Notifier__ drop-down, select the appropriate notifier. +4. Under the notifier name, select one of the following to specify where your notification message should go: + +* __All Devices__ to have the message sent to all devices. +* __Devices__ to have the message sent to a particular subset of devices. Enter a comma-separated list of device UUIDs in the box provided. +* __Users__ to have the message sent to a particular subset of users. Enter a comma-separated list of username values in the box provided. +* __Groups__ to have the message sent to a particular subset of user groups. Enter a comma-separated list of group paths in the box provided. + +5. In the __Notifier Message__ field, enter the message (payload) you want delivered. +6. If double-quotes are included in your message, you must escape them with a backslash. +7, Under __Delivery__, select one of the following to specify when the notification should be delivered: + +* __Now__ to have the message delivered immediately. +* Schedule for later to choose a date and time at which the message should be delivered. + +7. Click __Submit__. + +To create a notification to send multiple messages or target multiple platforms, see the cURL syntax for creating notifications. + +### Creating notificastions with iOS + +To send notifications from iOS app code, you use the 11ApigeeAPSDestination11 and ``ApigeeAPSPayload`` classes. + +With ``ApigeeAPSDestination``, you specify where the notification should go (a particular user or device or user group, for example). With ``ApigeeAPSPayload``, you specify the contents of the message, including any alert text, sound, or badge (items specified by Apple as allowable notification content types). You then use ``ApigeeDataClient`` to send the message via Apigee and Apple APNs. + +The following code illustrates how to send a notification to a single user. Though this is the device on which the app itself is installed, you can imagine how you might send a notification to another device, such as one belonging to someone "following" this user. For more, see the iOS push sample application included with the [Apigee iOS SDK](../sdks/tbd.html). + + - (void)sendMyselfAPushNotification:(NSString *)message + completionHandler:(ApigeeDataClientCompletionHandler)completionHandler + { + // send to a single device -- our own device + NSString *deviceId = [ApigeeDataClient getUniqueDeviceID]; + ApigeeAPSDestination* destination = + [ApigeeAPSDestination destinationSingleDevice:deviceId]; + + // set our APS payload + ApigeeAPSPayload* apsPayload = [[ApigeeAPSPayload alloc] init]; + apsPayload.sound = kBundledSoundNameWithExt; + apsPayload.alertText = message; + + // Example of what a custom payload might look like -- remember that + // APNS payloads are limited to a maximum of 256 bytes (for the entire + // payload -- including the 'aps' part) + NSMutableDictionary* customPayload = [[NSMutableDictionary alloc] init]; + [customPayload setValue:@"72" forKey:@"degrees"]; + [customPayload setValue:@"3" forKey:@"newOrders"]; + + __weak AppDelegate* weakSelf = self; + + // send the push notification + [dataClient pushAlert:apsPayload + customPayload:customPayload + destination:destination + usingNotifier:notifier + completionHandler:^(ApigeeClientResponse *response) { + if ( ! [response completedSuccessfully]) { + [weakSelf alert:response.rawResponse + title: @"Error"]; + } + + if (completionHandler) { + completionHandler(response); + } + }]; + } + +## Scheduling notifications + +### cURL + +To schedule a notification for a later time, add the deliver parameter with a UNIX timestamp to the body of your request. + +Request body syntax + + '{"deliver":,"payloads":{:}}' + +## Targeting multiple notifiers or messages +To send multiple messages or target multiple platforms with a single notification entity, include multiple notifier-message pairs as a comma-separated list in the payloads object of the request body: + +Request body syntax + + '{"payloads":{:, :, ...}}' + +## Setting a notification expiration +If a push service can't deliver a message to a device and needs to resend it (for example, if the device is turned off), you can set a notification to expire after a certain date/time. + +To do this, adding the expire parameter with a UNIX timestamp to your request body. This specifies when the service should stop trying to send the notification. + +

Warning


 +Please note that if the expire property is not set and Apple APNS or Google GCM are not able to immediately deliver your push notification, delivery will not be retried. This means your notification will not be delivered. As a best practice, you should always set an expire timestamp to ensure your notification is delivered in the event the delivery initially fails. +

+ +Request body syntax + + '{"expire":,"payloads":{"":""}}' + +NOTE: The timestamp is a UNIX timestamp and is specified in seconds. + + +## Getting notifications + +### cURL + +The following are endpoints can be used to get notifications. For details on the notification properties you can get, see Notifier, Receipt, and Notification. + +Getting one or more notifications: + + /notifications + +Getting notifications associated with one or more receipts: + + /receipts/*/notification + +Getting the list of devices associated with one or more notifications before the notifications are sent: + + /notifications/*/queue + +## Canceling sent notifications + +You can cancel a notification that's already in progress by doing the following: + + curl -X PUT "https://api.usergrid.com/my-org/sandbox/notifications/" -d '{"canceled": true}' + +### Admin portal + +You can view JSON for notifications by viewing their entity entries in the Data section of your application. + +In the admin portal, click Data, then click the __/notifications__ collection. +You can also view notification data in the message history. + +In the admin portal, click Push, then click Message History. +Locate the notification for which you want to view data, then click its view details link. + +## Deleting unsent notifications + +### Deleting unsent notifications with cURL + + curl -X DELETE "https://api.usergrid.com///notifications/" + +### Deleting unsent notifications with Admin Portal + +1. In the admin portal, click Push, then Message History. +2. On the Message History page, click Scheduled. +3. In the list of scheduled messages, locate the message you want to delete. +4. In the top area of the message item, click the delete link. + +## Getting receipts +After sending a notification, the BaaS generates a receipt entity that contains details about the notification. Receipts show details such as timestamps, payloads sent, and the receipt endpoints. + +For information about what's contained in a receipt, see [Notifier](..//rest-endpoints/api-docs.html#notifier), [Receipt](..//rest-endpoints/api-docs.html#receipt), and [Notification](..//rest-endpoints/api-docs.html#notification). Use the following endpoints to get receipts. + +To get one or more receipts: + + /receipts + +To get receipts associated with one or more devices: + + /devices/*/receipts + +To get receipts for one or more notifications. For example, get receipts for notifications that had errors. + + /notifications/*/receipts + +## Notification endpoints +The ``/notifications`` endpoints let you create, schedule, cancel, and delete notifications. You can also use the following endpoints to accomplish the same actions for specific groups, users, devices, or any combination thereof. + +Base URL: ``https://api.usergrid.com/my-org/my-app`` + + /groups/*/notifications + /groups/*/users/*/notifications + /groups/*/users/*/devices/*/notifications + /users/*/notifications + /users/*/devices/*/notifications + /devices/*/notifications + \ No newline at end of file diff --git a/content/docs/_sources/push-notifications/creating-notifiers.txt b/content/docs/_sources/push-notifications/creating-notifiers.txt new file mode 100644 index 0000000000..9e07176719 --- /dev/null +++ b/content/docs/_sources/push-notifications/creating-notifiers.txt @@ -0,0 +1,69 @@ +# Creating notifiers +When you request that a push notification be sent to your app on devices, an Usergrid notifier carries the request to the notification service (Google GCM or Apple APNs). + +A notifier is represented by an entity in your Usergrid application (see the [API Docs](../rest-endpoints/api-docs.html) for reference information). It carries the credentials that authorize your request. Once a notification service has verified that your notifier contains valid credentials, it will forward your push notification to your app on devices. + +You can create a notifier in two ways: using the admin portal and programmatically. + +

Note


 +For an overview of how to set up push notifications, including troubleshooting tips, see [Adding push notifications support](adding-push-support.html). +

+ +## Requirements +To create a notifier, you must first register your app with the appropriate notification service, as described in [Registering with a notification service](registration.html). + +## Creating notifiers with the admin portal +To create a notifier with the admin portal, do the following: + +1. Log in to the admin portal. +2. In the left nav, select __Push > Configuration__. +3. Click the __Apple__ or __Android__ tab. +4. If you have not already done so, retrieve your .p12 certificate (iOS apps) or API key (Android apps) by following the steps in the [Registering with a notification service](registration.html). +5. In the admin portal's Configuration page, enter values for the platform on which your mobile app will be installed. + +The fields are different depending on whether you are on the Apple or Android tab: + +__Fields for Apple__ + + + + + + + +
Name this notifier Enter a unique name that can be used to identify this notifiers.
Certificate Click __Choose File__ to select the .p12 certificate you generated and saved to your desktop earlier in this tutorial.
Environment Select the environment appropriate to your app. You may select development or production. Note that for the environment you select, you should have a separate .p12 certificate -- different certificates for development and production.
Certificate PasswordEnter a certificate password if one was specified when you created your .p12 certificate.
+ +__Fields for Android__ + + + + + +
Name this notifier Enter a unique name that can be used to identify this notifiers.
API KeyEnter the API key that was generated when you registered your app with GCM. To retrieve your API key, go to the [Google API developer web site](https://code.google.com/apis/console/), then select __APIs & Auth > Credentials__.
+ +6. Click __Create Notifier__. The Usergrid will create a notifier entity in the /notifiers collection. The notifier will also appear in the list of notifiers in the notifications console. + +## Creating notifiers programmatically +You can create an App BaaS notifier programmatically by sending requests to the Usergrid API. + +### For Apple + + curl -X POST -i -H "Accept: application/json" -H "Accept-Encoding: gzip, deflate" -H "Authorization: Bearer YWMtFeeWEMyNEeKtbNX3o4PU0QAAAT8vzK3xz3utVZat0CosiYm75C2qpiGT79c" -F "name=applenotifier" -F "provider=apple" -F "environment=development" -F "p12Certificate=@/Users/me/dev/pushtest_dev.p12" 'https://api.usergrid.com/my-org/my-app/notifiers' + +### For Google + + curl -X POST "https://api.usergrid.com/my-org/my-app/notifiers" -d '{"name":"androiddev", "provider":"google", "apiKey":"AIzaSyCkXOtBQ7A9GoJsSLqZlod_YjEfxxxxxxx"}' + +## Notifier endpoints + +The following are the available notifier endpoints. For details on notifier properties, see the [API Docs](../rest-endpoints/api-docs.html). + +Base URL: ``https://api.usergrid.com/my-org/my-app/`` + +Working with one or more notifiers: + + /notifiers + +Working with notifiers associated with specific devices: + + /devices/{device-id}/notifier diff --git a/content/docs/_sources/push-notifications/getting-started.txt b/content/docs/_sources/push-notifications/getting-started.txt new file mode 100644 index 0000000000..6f1b80f70b --- /dev/null +++ b/content/docs/_sources/push-notifications/getting-started.txt @@ -0,0 +1,102 @@ +# Getting started with push notifications + +## What are push notifications? +Usergrid provides a RESTful framework for sending push notifications to your apps, giving you full control over which app users you target, as well as when you send notifications. You can send messages to devices, users, or groups that have specific characteristics and locations. (To receive push notifications, users must be using devices that can connect to the Usergrid). Here are just a couple reasons for enabling push notification support in your app with Usergrid: + +* __Reach your app's users__ with messages they care about. This could be a flash sale happening near them right now (use [geolocation](../geolocation/geolocation.html)!) or a lunch special at a favorite restaurant. You could even let a user know it's her turn in a game she's playing with a friend. +* __Keep your app footprint low__ while communicating in a high-value way with your app's users. Compare pushing data with CPU- and memory-heavy pull processes. In those, an app actively listens on an endpoint, regularly pulling data (such as news feeds, new emails, or stock market updates) to the device. + +
+ +
+ +

+ +## Prerequisites +You will need to test with a mobile device running the platform you're developer for. In the case of Android, you might be able to use an emulator. It is not possible to test push notifications from a web browser. + +### iOS Prerequisites +To develop push notifications for an iOS app, you'll need: + +* A Mac to generate the necessary SSL certificate. +* An iOS developer account. You'll need this to register for an App ID and get a provisioning profile. To get an account, visit the [iOS Dev Center](https://developer.apple.com/ios/download/). +* An actual iOS device to test push notifications. It's not yet possible to develop push notifications with an emulator. +* An iOS provisioning profile +For iOS app testing, you need a provisioning profile that's associated with an Apple ID. You set up the provisioning profile in the Apple developer portal, download the profile, and import it into Xcode. + +To set up a provisioning profile, you need to create an "iOS App Development" certificate in the Apple developer portal. For example, in the Apple APNs setup earlier in this tutorial, you created a certificate in the Apple developer portal to be used for push notifications. However, you won't be able to create a provisioning portal with just that certificate. You also need to create an "iOS App Development" certificate (the configuration settings don't matter), as shown in the following image. + +.. image:: ios-cert.png + +After you create an iOS App Development certificate, you can create a provisioning profile that includes your App ID/certificate for push notifications. + +### Android Prerequisites + +It's generally a best practice to develop Android apps by testing and debugging with an Android device. It's also possible to use an emulator. + +Before testing and debugging with an Android device, you'll need to set up your device for development. Be sure to see the Android documentation on [using hardware devices](http://developer.android.com/tools/device.html). + +To test with an emulator, you will need to follow these steps: + +1. Ensure that you have Google API 8 (or above) and Android 2.2 (or above). +2. Using the Android SDK Manager, install Google Cloud Messaging for Android Library. +3. Using the Android Virtual Device Manager, create an emulator whose target is Google APIs. +4. Ensure that the emulator you're using includes a Google account. + +Next: + +* Launch the emulator. +* In the emulator, click the Menu button, then go to Settings > Accounts & Sync. +* Add a Google account. +* Once you've finished these steps, you should have an emulator that can receive push notification messages. + +### PhoneGap Prerequisites + +You'll need to test with a device or emulator. It is not possible to test push notifications with a browser alone. + +## Setup overview +The following steps get you set up so that your app can receive push notifications. Keep in mind that these steps build on one another. In other words, you'll need values generated in step 1 in order to complete step 2, and so on. + +For a walkthrough of these steps using a push sample app, see Tutorial: Push notifications sample app. + +1. __Register__ your app with push notification services. Your notification messages will be forwarded to devices by Apple and/or Google. So you'll need to register with Apple APNs and/or Google's GCM. For more information, see Registering with a notification service. + +2. __Create a notifier__ to send notification messages from the Usergrid to notification services. +The Usergrid will use your notifier to send your messages to a notification service. For details, see Creating notifiers. To create a notifier, you'll need information generated by registering with a push notification service. You'll need a separate notifier for each app/platform combination. + +3. __Register devices at run time__. +At run time, your code will register to receive notifications. To do this, your code uses information from the notification service and your notifier. For more, see Managing users and devices. + +4. __Send and manage push notifications__. +You use Usergrid API notification endpoints to target devices, users, or groups with your messages. To learn more, see Creating and managing notifications. + + +## How it works +Click a tab below to view more information about how the pieces connect once you've got it set up. + +### Apple APNs + +The diagram below illustrates what things should look like once you've gotten set up to send notifications that are received by your app. + +__A.__ At configuration time, you [create an App ID](registering.html), then [create a notifier](creating-notifiers.html) with a .p12 certificate you generate on your Mac. The .p12 certificate correlates the notifier (which you will use to send notification messages) with the App ID (so that APNs will forward your notifications to devices). + +__B.__ A run time, your app's code [registers with Apple for notifications](managing-users-and-devices.html) by invoking the ``registerForRemoteNotificationTypes`` method to receive a token it can send to Usergrid. + +__C.__ At run time, your app's code [registers with the Usergrid for notifications](managing-users-and-devices.html) by sending the name of the notifier you created. This ensure's that there's a device entity in your Usergrid application. That way, you can address the device with notification messages. + +.. image:: pushmiddleios0.png + +__Note__: For information on troubleshooting push notifications on iOS devices, see [Troubleshooting Push Notifications](troubleshooting.html) + +### Google GCM + +The diagram below illustrates what things should look like once you've gotten set up to send notifications that are received by your app. + +__A.__ At configuration time, you [create a Google API project](registering.html)), then [create an Usergrid notifier](creating-notifiers.html) with an API key from the project. The API key correlates the notifier (which you will use to send notification messages from the Usergrid) with the API project (which will forward your notifications to devices). + +__B.__ At run time, your app's code [registers with the Usergrid](managing-users-and-devices.html)) for notifications by sending the name of the notifier you created. This ensure's that there's a device entity in your Usergrid application. That way, you can address the device with notification messages. + +__C.__ A run time, your app's code [registers with Google for notifications](managing-users-and-devices.html)) by sending the number of your API project as a "sender ID". The project is the actual notification "sender" that will forward notifications to your app. In other words, the app is telling Google that it wants to receive notifications from that sender. + +.. image:: pushmiddleandroid0.png + \ No newline at end of file diff --git a/content/docs/_sources/push-notifications/managing-users-and-devices.txt b/content/docs/_sources/push-notifications/managing-users-and-devices.txt new file mode 100644 index 0000000000..4f04f9a3ee --- /dev/null +++ b/content/docs/_sources/push-notifications/managing-users-and-devices.txt @@ -0,0 +1,313 @@ +# Managing users and devices +Before your app can receive notifications on a user's device, the app's code will need to register the device with both the Usergrid and the appropriate push notification service (Apple APNs or Google GCM). + +By registering with the Usergrid, your app adds the device on which it is installed to your data store. The device is represented as a Device entity. This makes it possible for you to target that device when sending notifications. (For more on the Device entity, see the [API Docs](../rest-endpoints/api-docs.html).) Any devices, users, and groups that have been registered in this way may be targeted with push notifications. + +By registering with the notification service, you make the device known to the service. This way, the service can forward your notifications to the device. + +

Note


 +For an overview of how to set up push notifications, including troubleshooting tips, see [Adding push notifications support](adding-push-support.html). +

+ +## Registering devices +The following samples illustrate how to register a device with a notification service and with the Usergrid. At a high level, your code will send a registration request to the notification service, then use information in the service's response to send a separate request to the Usergrid. The two requests correlate the notification service, Usergrid, and your mobile app. + +You can also create device entities separately by using the /devices endpoint. For more information on using the ``/devices`` endpoint in the Usergrid, see the [API Docs](../rest-endpoints/api-docs.html). + +Registering a device with a notification service is a standard coding activity for implementing push notifications. This is not specific to the Usergrid. + + +### Registering for iOS + +The following code illustrates how you can use the iOS SDK to register a device with both the Usergrid server and with the APNs, the Apple push notification service. This example assumes that your code has already property initialized the SDK. For more information, see [Installing the Apigee SDK for iOS](../sdks/tbd.html). + + // Register with Apple to receive notifications. + + // Invoked when the application moves from an inactive to active state. Use this + // method to register with Apple for notifications. + - (void)applicationDidBecomeActive:(UIApplication *)application + { + // Find out what notification types the user has enabled. + UIRemoteNotificationType enabledTypes = + [application enabledRemoteNotificationTypes]; + + // If the user has enabled alert or sound notifications, then + // register for those notification types from Apple. + if (enabledTypes & (UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeSound)) { + + // Register for push notifications with Apple + NSLog(@"registering for remote notifications"); + [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | + UIRemoteNotificationTypeSound]; + } + } + + // Invoked as a callback from calling registerForRemoteNotificationTypes. + // newDeviceToken is a token received from registering with Apple APNs. + // Use this method to register with Apigee. + - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)newDeviceToken + { + // Register device token with the Usergrid (will create the Device entity if it doesn't exist) + // Sends the name of the notifier you created with Apigee, along with the token your code + // received from Apple. + ApigeeClientResponse *response = [dataClient setDevicePushToken: newDeviceToken + forNotifier: notifier]; + + if ( ! [response completedSuccessfully]) { + [self alert: response.rawResponse title: @"Error"]; + } + } + + // Invoked as a callback from calling registerForRemoteNotificationTypes if registration + // failed. + - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error + { + [self alert: error.localizedDescription title: @"Error"]; + } + +Initialize the Apigee client and check for notifications that might have been sent while the app was off. + + // Invoked as a callback after the application launches. + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions + { + // Connect and login + ApigeeClient *apigeeClient = + [[ApigeeClient alloc] initWithOrganizationId:orgName + applicationId:appName + baseURL:baseURL]; + dataClient = [apigeeClient dataClient]; + [dataClient setLogging:true]; //comment out to remove debug output from the console window + + // Find out if there's a notification waiting to be handled after the + // app launches. + if (launchOptions != nil) { + NSDictionary* userInfo = + [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; + + // If there's notification data waiting, send it to be processed. + if (userInfo) { + [self handlePushNotification:userInfo + forApplication:application]; + } + } + + // It's not necessary to explicitly login if the Guest role allows access. + // But this is how you can do it. + // [apigeeClient logInUser: userName password: password]; + + NSLog(@"done launching"); + return YES; + } + +### Registering for Android + +The following code illustrates how to register a client device with GCM, register the device with Apigee, and associate the device with the user. Methods used in this code are defined in the Apigee Android SDK. For more information on downloading and installing the SDK, see Installing the Apigee SDK for Android. + + import android.content.Context; + import com.google.android.gcm.GCMRegistrar; + import com.apigee.sdk.ApigeeClient; + import com.apigee.sdk.data.client.entities.Device; + + /** + * Registers this device with GCM, Google's messaging + * service. + * + * @param context An Android context with information specific to this + * application's context on the device. + */ + static void registerPush(Context context) { + + //Get an instance of the Apigee DataClient class from the ApigeeClient object + dataClient = getClient().getDataClient(); + + // Get the registration ID (GCM API key) for this application. + final String regId = GCMRegistrar.getRegistrationId(context); + + // If this device isn't already registered with GCM, register it + // using the the application context and an ID for the Google account + // authorized to send messages to this application. This is the + // Google Client ID from Google API Console. + if ("".equals(regId)) { + GCMRegistrar.register(context, gcmSenderId); + } else { + if (GCMRegistrar.isRegisteredOnServer(context)) { + Log.i(TAG, "Already registered with GCM"); + } else { + + // Use an instance of the Client class (SDK for Android) + // to register this device with the Usergrid. Pass as arguments + // the device unique identifier, the unique name of the notifier you + // created in the Usergrid, the GCM API key, and a callback that will + // receive an instance of a Device class representing the registered + // device on the system. + dataClient.registerDeviceForPushAsync(dataClient.getUniqueDeviceID(), notifierName, regId, null, + new DeviceRegistrationCallback() { + @Override + public void onResponse(Device device) { + AppServices.device = device; + + // Associate the logged in user with this device. + if (dataClient.getLoggedInUser() != null) { + dataClient.connectEntitiesAsync("users", + dataClient.getLoggedInUser().getUuid().toString(), + "devices", device.getUuid().toString(), + new ApiResponseCallback() { + @Override + public void onResponse(ApiResponse apiResponse) { + Log.i(TAG, "connect response: " + apiResponse); + } + + @Override + public void onException(Exception e) { + displayMessage(context, "Connect Exception: " + e); + Log.i(TAG, "connect exception: " + e); + } + }); + } + } + + }); + } + } + } + + /** + * Create an instance of the SDK ApigeeClient class, setting + * values from your Apigee registration. + */ + static synchronized ApigeeClient getClient() { + if (client == null) { + client = new ApigeeClient(); + client.setApiUrl("https://api.usergrid.com"); + client.setOrganizationId("your-org"); + client.setApplicationId("your-app"); + } + return client; + } + + +### Registering for HTML5/PhoneGap + +The following code illustrates how you can use the JavaScript functions included with the PhoneGap plugin to register a device with both the Apigee server and with the APNs, the Apple push notification service. + + // Declare a variable for calling push notification APIs. + var pushNotification = window.plugins.pushNotification; + // Collect configuration options to specify that this device accepts + // an alert message, an application badge, and a sound. + var appleOptions = { + alert:true, badge:true, sound:true + }; + // Register the device with the Usergrid, passing options for configuration + // along with a callback from which you can retrieve the device token + // sent by Apigee. + pushNotification.registerDevice(appleOptions, function(status) { + console.log(status); + // If a token was received, bundle options to pass when registering the device + // with the push notification service. The provider value must be "apigee" to + // support push notification through Apigee. orgName and appName should be + // values corresponding to those used in your Apigee account. + // notifier is the unique name you associated with the Apigee notifier you created. + // token is the device token this code received from Apigee after registering the + // device. + if(status.deviceToken) { + var options = { + "provider":"apigee", + "orgName":"YOUR APIGEE.COM USERNAME", + "appName":"sandbox", + "notifier":"YOUR NOTIFIER", + "token":status.deviceToken + }; + + // Use the device token and other options to register this device with the + // push notification provider. + pushNotification.registerWithPushProvider(options, function(status){ + console.log(status); + }); + } + }); + +The functions used in this code are defined in the PhoneGap plugin. JavaScript functions invoke underlying Objective-C or Java code (depending on platform). You'll find that code in these files, included in the Apigee PhoneGap push notification plug-in. + +Information about installing the plugin is available in its Readme file. For more complete examples, see [Tutorial: Push notifications sample app](tutorial.html). + + +## Connecting devices to users +You can associate user entities with device entities in the Usergrid. Doing so allows you to target your push notifications at users with specific characteristics. The following describes how to connect a user to a specific device in the Usergrid. + +For more information on creating a device in your Usergrid data store, see "Registering Devices" above. + +For more information on creating a user in your Usergrid data store, see [User](../rest-endpoints/api-docs.html#user). + +The following code examples all use the same basic endpoint pattern for connecting devices with users: + + POST /users/{userUUID or name}/devices/{deviceUUID} + +### Connecting with curl +The following call connects user "joex" with device 7a0a1cba-9a18-3bee-8ae3-4f511f12a386 (the device UUID). After this connection, you can send a push notification to joex rather than the device. Further, if joex has specific properties set--such as {"favoritecolor": "blue"}--you can send a push notification to all users whose favorite color is blue (assuming they're connected to devices in the Usergrid). + + curl -X POST "https://api.usergrid.com/my-org/sandbox/users/joex/devices/7a0a1cba-9a18-3bee-8ae3-4f511f12a386" + +### Connecting with iOS + +The following sample code, taken from AppDelegate.m in the native iOS push sample, uses the connectEntities method from the iOS SDK to connect a device to a user. + + ApigeeClientResponse *response = [dataClient setDevicePushToken: newDeviceToken forNotifier: notifier]; + + // You could use this if you log in as an Usergrid user to associate the Device to your User + if (response.transactionState == kUGClientResponseSuccess) { + response = [self connectEntities: @"users" connectorID: @"me" type: @"devices" connecteeID: deviceId]; + } + +### Connecting with Android + +The following sample code, taken from [AppServices.java](https://github.com/apigee/appservices-android-push-example/blob/master/src/com/ganyo/pushtest/AppServices.java) in the native Android push sample, uses the connectEntitiesAsync method from the Android SDK to connect a device to an authenticated user. + + // connect Device to current User - if there is one + if (dataClient.getLoggedInUser() != null) { + dataClient.connectEntitiesAsync("users", dataClient.getLoggedInUser().getUuid().toString(), + "devices", device.getUuid().toString(), + new ApiResponseCallback() {... + +### Connecting with HTML5/JavaScript + +The following code illlustrates how to associate the currently logged in user with their device. + + // You'll need a client from the JavaScript SDK. + var client = new Apigee.Client({ + // Initialize client. + }); + + // Get information about the current user so you can use + // it to connect them with their device. + client.getLoggedInUser(function(err, data, user) { + if(err) { + // Could not get the logged in user. + } else { + if (client.isLoggedIn()) { + // Using a PushNotification function to get the device ID as + // it is known to the Apigee system. + pushNotification.getApigeeDeviceId(function(results) { + if (results.deviceId) { + // Use the JavaScript SDK connect function to register + // a connection between the current user and their device. + user.connect('devices', results.deviceId, function (err, data) { + if (err) { + // Could not make the connection. + } else { + // Call succeeded, so pull the connections back down. + user.getConnections('devices', function (err, data) { + if (err) { + // Couldn't get the connections. + } else { + // Connection exists. + }); + } + } + } + } + } + } + } + +You can also connect users with groups so that you can send push notifications to groups of users (and their associated devices), see [Working with group data](../user-management/group.html). + diff --git a/content/docs/_sources/push-notifications/overview.txt b/content/docs/_sources/push-notifications/overview.txt new file mode 100644 index 0000000000..32fb451858 --- /dev/null +++ b/content/docs/_sources/push-notifications/overview.txt @@ -0,0 +1,58 @@ +# Push notifications overview + + + + + + +
+ +.. image:: iphonemessage.png + + + +## Reach your users with push +With the new push notifications feature in the Usergrid, you can send announcements to your app's users. + +* __Reach your app's users__ with messages they care about. +* __Keep your app footprint low__ while communicating in a high-value way with your app's users. + +[Read more](getting-started.html) + +
+ +

+ +## Get started + +#### [Get started with a tutorial](tutorial.html) +Build your first push-enabled app using an Apigee sample. + +#### [Find what you can do with it](getting-started.html) +A video and introduction. + +#### [See the prerequisites](getting-started.html#prerequisites) +Depending on your supported app platforms, you'll need just a few things. + + +## Build push support + +#### [Setting up push notifications support](getting-started.html) +Connect Apple or Google with Usergrid and your app. + +#### [Register your app](registering.html) +Register with Apple or Google. + +#### [Create a notifier](creating-notifiers.html) +Your application uses this to send messages. + +#### [Register client devices](managing-users-and-devices.html) +Your app code registers to receive notifications. + +#### [Send and manage notifications](creating-and-managing-notifications.html) +You can do this from app code or the admin portal. + +## Learn more + +#### [Troubleshoot your push support](troubleshooting.html) +Things don't work as you expect? \ No newline at end of file diff --git a/content/docs/_sources/push-notifications/registering.txt b/content/docs/_sources/push-notifications/registering.txt new file mode 100644 index 0000000000..893058352a --- /dev/null +++ b/content/docs/_sources/push-notifications/registering.txt @@ -0,0 +1,102 @@ +# Registering with a notification service +To send push notifications, you will need to first register your app with the push notification service (Apple APNs or Google GCM) that corresponds to your app's platform. Once you've registered, the service will provide you with a certificate or key that you will need when you create an Usergrid notifier. (See [Creating notifiers](creating-notifiers.html) for more information.) + +Push notification services are gateways controlled by platform services (such as Apple and Google). These gateways ensure that push notifications are delivered securely and originate from trusted apps. + +To send push notifications to your app on iOS devices, you’ll register the the Apple Push Notification service (APNs). For app on Android, you’ll register with Google Cloud Messaging for Android (GCM). + +

Note


 +For an overview of how to set up push notifications, see [Setting up push notification support](adding-push-support.html). +

+ +## Registering with Apple APNs +Before you can send push notifications to your app on iOS devices, you'll need to get set up so that Apple knows you'll be sending notifications. To do that, you'll need to do the following: + +* Generate an SSL signing certificate you can use to generate a .p12 certificate. +* Create an Apple App ID through which you can associate push notifications support with your app. +* Generate a .p12 certificate you can use to create an Usergrid notifier. The certificate will be sent to APNs with push notification requests. + +For more information see "How the pieces connect" in [Setting up push notification support](getting-started.html). + +

Note


 +You'll need a Mac to generate a .p12 certificate and work with APNs. +

+ +### Generating an SSL signing certificate +First, you'll create an SSL signing certificate that you can use to generate a .p12 certificate. To generate an SSL signing certificate, do the following: + +1. On your development machine, launch the Keychain Access application. +2. From the Keychain Access menu, select __Certificate Assistant > Request a Certificate From a Certificate Authority__. +3. Enter a contact email address and a name you will use to sign your apps. +4. Select __Saved to disk__, then click __Continue__. +5. Select __Desktop__ from the Where drop-down, then click __Save__ to download the .certSigningRequest file. +6. Click __Done__ once the download has completed. + +### Creating an App ID + +Next, you must create an App ID for your app. The App ID uniquely identifies your app and provides a way for you to configure the app for push notification support. (For more on App IDs, see [Creating and Configuring App IDs](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingProfiles/MaintainingProfiles.html).) + +

Note


 +An iOS developer account is required to complete these steps. To register for an iOS developer account, visit the [Apple Developer site](https://developer.apple.com/). +

+ +1. Log in to [Apple's iOS developer portal](https://developer.apple.com/ios/manage/overview/index.action). +2. In the iOS Apps section, click __Identifiers__, then select __App IDs__. +3. Click the + icon to create a new App ID, and enter the following: + +* __App ID Description - Name__: A unique name that identifies your app. +* __App BaaS__: Select Push Notifications. +* __App ID Suffix__: Select Explicit App ID, and enter your desired App ID in reverse-domain format. For example, com.apigee.pushapp. + +4. Click __Submit__ to create the App ID, then click __Done__. You will be returned to the App IDs page. + +### Generating a .p12 certificate + +Finally, you will generate the .p12 certificate using the App ID and signing certificate you created in the previous steps. The .p12 certificate will be sent by Apigee to Apple APNs with all push notification requests. A unique .p12 certificate is required for each app. In addition, you should create separate .p12 certificates for development and production versions of your app. + +1. On the App IDs page, click your new App ID, then click Edit. +2. In the Push Notifications section, under Development SSL Certificate, click Create Certificate. + +.. image:: pushsslcertificate.png + +3. Click __Choose File__, select the .certSigningRequest file you saved to your Desktop in the previous section, then click __Generate__. +4. Click __Done__. You will be returned to the App ID settings window. +5. In the Push Notifications section, click __Download__ to save the certificate (aps_development.cer file) to your Desktop. +6. Double-click the .cer file to install it in your keychain. The newly installed certificate will appear in your Keychain Access application under My Certificates with a name similar to "Apple Development iOS Push Services: ". +7. Control-click the certificate and select __Export__. +8. Save the certificate to your Desktop as a 'Personal Information Exchange (.p12)' file. (You'll need this file when you create a notifier. For more information, see [Creating notifiers](creating-notifiers.html). +9. In the password dialog, leave the password field blank, then click __OK__. +10. In the next dialog, enter your system password, then click __Allow__. + + +## Registering with Google GCM +To create a notifier for sending notifications, you'll need a Google API project and register your app as part of that project. The project's identifier (project number) will become the sender ID your client code will send when registering. Registering your app will give you an API key you'll use to create a notifier. (For more information see "How the pieces connect" in [Adding push notifications support](adding-push-support.html).) + +The following is an abbreviated version of the steps described in the Google documentation on [getting started with Google Cloud Messaging](http://developer.android.com/google/gcm/gs.html). + +To generate a project number and API key, do the following: + +1. Go to the [Google API developer web site](https://code.google.com/apis/console/) and log in with your Google ID. + +2. Click __Create Project__, enter a project name and ID, then follow the steps required to verify. + +3. In the left nav, click __Overview__ to view the project number. Note this number for later use in client code. + +.. image:: googleproj0.png + +4. Click __APIs__ in the left nav area, then click the button to enable __Google Cloud Messaging for Android__. + +.. image:: gcmsetting.png + +5. In the left nav, under __APIs and auth__, click __Credentials__. + +6. Under __Public API access__, click __Create New Key__. + +7. In the __Create a new key__ dialog, click __Server key__. Take care not to choose "Android key," though you might be tempted to. Remember that your push notification requests will be received by Google from Apigee's server (via the notifier your code sends to Apigee), rather than directly from the device your app is installed on. + +8. On the __Create a server key...__ dialog, enter the IP address of the server that will be sending the notification request to Google. + +9. Click __Create__. + +10. On the Credentials page, under __Key for server applications__, copy the __API key__ value for use when creating a notifier to request push notifications from GCM. (For more information, see [Creating notifiers](creating-notifiers.html).) + diff --git a/content/docs/_sources/push-notifications/tbd.txt b/content/docs/_sources/push-notifications/tbd.txt new file mode 100644 index 0000000000..1b5ca73213 --- /dev/null +++ b/content/docs/_sources/push-notifications/tbd.txt @@ -0,0 +1 @@ +# COMING IN USERGRID 2 \ No newline at end of file diff --git a/content/docs/_sources/push-notifications/troubleshooting.txt b/content/docs/_sources/push-notifications/troubleshooting.txt new file mode 100644 index 0000000000..15cab029a4 --- /dev/null +++ b/content/docs/_sources/push-notifications/troubleshooting.txt @@ -0,0 +1,93 @@ +# Troubleshooting + +## Working with Android + +### App fails to install on the emulator + +* When using the emulator, be sure to note the setup steps in [Push notifications prerequisites](getting-started.html#prerequisites). + +* Sometimes installation fails while the emulator is still being launched. Wait until the emulator is up and running (so that you can unlock and interact with the UI), then run the project again. + +* Make sure that the order of your Java Build Path matches the order shown in [Tutorial: Push notifications sample app](tutorial.html). + +### Push errors +If pressing the button to send yourself a push throws an exception or doesn't respond: + +* Make sure the emulator's target matches the Google API version used in the project. + +* In the IDE log, wait until you see that the device has been registered before sending yourself a push. +Sometimes waiting for the code to run and trying another click gets the push message to you. + +* If you successfully send yourself a push message once but fail to again, try one of the following: + +Go to the apps list on the device and launch the app from there. + +OR + +Uninstall the app from the device, delete the device in the admin portal, and run the project again. + +### MismatchSenderId error message from the server when it tries to send a message to your app. +The sender ID is a number you send to GCM from app code when registering with GCM for notifications. The error might be occurring because the sender ID with which your app is registering at GCM for notifications does not correlate to the API project whose API key was used to create your notifier. First, confirm the following: + +* The sender ID in your app code (used when registering with GCM) is the same as your Goole API project number. + +* The API key used to create your notifier is the same as the API key in your Google API project. + +* The notifier name used in your app code is the same as for the notifier you created in the Usergrid. + +It can be possible to make a fix (such as by correcting the sender ID in your app code) and still see this error. If you're still seeing the error, consider create a new API project and notifier, then use their new values in your code: + +1. Recreate (or create anew) the Google API project. This will generate a new API key and project number. See Registering with a notification service. + +2. Create a new notifier for GCM using the API key you generated with the new API project. See Creating notifiers. + +3. Use the new notifier name in your code, along with a new sender ID that is that same value as the Google API project number. + +### INVALID_SENDER error message +The sender ID is a number you send to GCM from app code when registering with GCM for notifications. The "sender" in this case is the Google API project you created to send notification messages. Confirm that the sender ID you're using in code is the same value as the API project number generated when you created your Google API project. See Registering with a notification service. + +## Working with PhoneGap Android + +### App fails to install on the emulator + +* When using the emulator, be sure to note the setup steps in [Tutorial: Push notifications sample app](tutorial.html). + +* Sometimes installation fails while the emulator is still being launched. Wait until the emulator is up and running (so that you can unlock and interact with the UI), then run the project again. + +* Make sure that the order of your Java Build Path matches the order shown in [Tutorial: Push notifications sample app](tutorial.html). + +### Push errors +If pressing the button to send yourself a push throws an exception or doesn't respond: + +* Make sure the emulator's target matches the Google API version used in the project. + +* In the IDE log, wait until you see that the device has been registered before sending yourself a push. +Sometimes waiting for the code to run and trying another click gets the push message to you. + +* If you successfully send yourself a push message once but fail to again, try one of the following: + +Go to the apps list on the device and launch the app from there. + +OR + +Uninstall the app from the device, delete the device using the admin portal, then run the project again. + +### MismatchSenderId error message from the server when it tries to send a message to your app. +The sender ID is a number you send to GCM from app code when registering with GCM for notifications. The error might be occurring because the sender ID with which your app is registering at GCM for notifications does not correlate to the API project whose API key was used to create your notifier. First, confirm the following: + +* The sender ID in your app code (used when registering with GCM) is the same as your Google API project number. + +* The API key used to create your notifier is the same as the API key in your Google API project. + +* The notifier name used in your app code is the same as for the notifier you created in the Usergrid. + +It can be possible to make a fix (such as by correcting the sender ID in your app code) and still see this error. If you're still seeing the error, consider create a new API project and notifier, then use their new values in your code: + +1. Recreate (or create anew) the Google API project. This will generate a new API key and project number. See [Registering with a notification service](registration.html). + +2. Create a new notifier for GCM using the API key you generated with the new API project. See [Creating notifiers](creating-notifiers.html). + +3. Use the new notifier name in your code, along with a new sender ID that is that same value as the Google API project number. + +### INVALID_SENDER error message +The sender ID is a number you send to GCM from app code when registering with GCM for notifications. The "sender" in this case is the Google API project you created to send notification messages. Confirm that the sender ID you're using in code is the same value as the API project number generated when you created your Google API project. See [Registering with a notification service](registration.html). diff --git a/content/docs/_sources/push-notifications/tutorial.txt b/content/docs/_sources/push-notifications/tutorial.txt new file mode 100644 index 0000000000..8ebecfe024 --- /dev/null +++ b/content/docs/_sources/push-notifications/tutorial.txt @@ -0,0 +1,251 @@ +# Tutorial: Push notifications sample app +In this tutorial, you'll use a sample app (iOS, Android, or PhoneGap) to send yourself a push notification with the Usergrid push notification API. You'll register with a push notification services (Apple APNs or Google GCM) to create the required security certificate or key, create the required Usergrid notifier to send a message, then modify, compile and run the sample app to see push notifications in action. + +

Note


 +For an overview of how to set up push notifications, including troubleshooting tips, see [Adding push notifications support](adding-push-support.html). +

+ +## Before you begin +Before you can add support for push notifications, be sure that you're set up for the requirements described in Adding push notifications support. + +## Step 1: Download a sample app +Sample push notification apps are included in the /samples directory of the following platform SDKs and plugins: + +* Native iOS [Download the SDK](http://www.apigee.com/docs/content/ios-sdk-redirect) + +* Native Android [Download the SDK](http://www.apigee.com/docs/content/android-sdk-redirect) + +* PhoneGap iOS & Android (HTML5) [Download the SDK](http://www.apigee.com/docs/content/javascript-sdk-redirect + +To begin this tutorial, download the sample app for the platform of your choice. + +__A note to PhoneGap developers__: PhoneGap requires a plugin to enable push notifications. The plugin is included in the sample apps in the JavaScript SDK. For new PhoneGap applications, [download the PhoneGap push plugin](https://github.com/phonegap-build/PushPlugin). + +## Step 2: Register with a notification service and generate a certificate/key +To send push notifications you must register your app with the push notification service that corresponds to your app's platform. Once registered, the service will provide you with a certificate or key that you will provide when creating an Usergrid notifier. + +For a full walkthrough of how to register an app with a notification service and generate the necessary certificate/key, see [Registering with a notification service](registration.html). + +## Step 3: Create a notifier +Notifiers are entities that carry your push notifications to a notification service. Once a notification service has verified that your notifier contains valid credentials, it will deliver your push notification to the devices of your app's users. + +For information on how to use the admin portal to create a notifier, see [Creating notifiers](creating-notifiers.html). + +## Step 4: Configure and run the sample app +In this step, you'll open your sample app of choice in your IDE and configure it. The Android sample app can be run with an emulator, included in the Android Developer Tools. The iOS sample app must be run on an actual iOS device. + +The following sections provide platform-specific guidance for setting up and running the samples. However, this content assumes that you understand your development environment well enough to configure and work with projects. + +### iOS Dev Setup + +To configure and run the Native iOS push notification sample app, do the following: + +1. Open the iOS sample app with XCode by opening its .xcodeproj file. + +2. Make the following changes to __/Push Test/AppDelegate.m__: + +* __orgName__: Your Apigee organization. + +* __appName__: The app in your organization where you created the notifier. (For the sample, make sure it's "sandbox".) + +* __notifier__: Name of the notifier you created. (For the sample, make sure it's "appledev".). + +3. Plug your iOS device into your development machine. + +4. In Xcode, select __Window > Organizer__ to open the Xcode Organizer. + +5. Under __Devices__, select the device you plugged in, then click __Add to Member Center__. You may be prompted to log in with the Apple ID associated with your Apple Developer account. + +6. If prompted, select a Development Team to use for provisioning. This will be a team you've registered at the Apple developer portal. + +7. Log in to the [Apple Developer portal](https://developer.apple.com/) and create a provisioning profile that includes the App ID you chose when you registered the sample app with Apple APNs. For more information on how to create a provisioning profile, see "About provisioning profiles" below. + +8. Download the profile and add it into Xcode Organizer, in the Provisioning Profiles group under your plugged-in device. + +9. Close the Organizer. + +10. In Xcode, select the Project Navigator, then select the project root folder. + +11. In the __General__ tab, in the __Bundle Identifer__ box, enter the App ID associated with your provisioning profile. + +12. In the __Build Settings__ tab, under __Deployment__, for the __iOS Deployment Target__ select the iOS version on your connected device. The version is displayed in the Xcode Organizer. + +13. In the __Build Settings__ tab, under __Code Signing__, under __Code Signing Identity > Debug__, select the Apple signing certificate corresponding to your developer identity. + +.. image:: iospushsettings.png + +14. Click __Run__ to launch the sample on your iOS device. + +15. When the "codesign wants to sign using key in your keychain." dialog is displayed, click __Allow__. + +16. The project is now built, and the app is installed on your device. The first time you run the push sample app, your device will ask permission to allow push notifications. Tap __OK__. + +.. image:: iospushauth.png + +17. In the app, tap the __push to this device__ button to send yourself a push notification. If you have configured your notification to go to multiple devices, tap the __push to all devices__ button to send the push notification to all devices. + +.. image:: iospushfinal.png + +### PhoneGap iOS Dev Setup + +To configure and run the PhoneGap iOS push notification sample app, do the following: + +1. Open the iOS PhoneGap sample app with Xcode by opening its .xcodeproj file. + +2. Make the following changes in __/www/js/index.js__: + +* __orgName__: Your Apigee organization. + +* __appName__: The app in your organization where you created the notifier. (For the sample, make sure it's "sandbox".) + +* __notifier__: Name of the notifier you created. + +3. Plug your iOS device into your development machine. + +4. In Xcode, select __Window > Organizer__ to open the Xcode Organizer. + +5. Under __Devices__, select the device you plugged in, then click __Add to Member Center__. You may be prompted to log in with the Apple ID associated with your Apple Developer account. + +6. If prompted, select a Development Team to use for provisioning. This will be a team you've registered at the Apple developer portal. + +7. Log in to the [Apple Developer portal](https://developer.apple.com/) and create a provisioning profile that includes the App ID you chose when you registered the sample app with Apple APNs. For more information on how to create a provisioning profile, see "About provisioning profiles" below. + +8. Download the profile and add it into Xcode Organizer, in the Provisioning Profiles group under your plugged-in device. + +9. Close the Organizer. + +10. In Xcode, select the Project Navigator, then select the project root folder. + +11. In the __General__ tab, in the __Bundle Identifer__ box, enter the App ID associated with your provisioning profile. + +12. In the __Build Settings__ tab, under __Deployment__, for the __iOS Deployment Target__ select the iOS version on your connected device. The version is displayed in the Xcode Organizer. + +13. In the __Build Settings__ tab, under __Code Signing__, under __Code Signing Identity > Debug__, select the Apple signing certificate corresponding to your developer identity. + +.. image:: iospgsettings.png + +14. At the top of the IDE, ensure that the name for your plugged in device is displayed next to the target name, then click the Run button to launch the sample on your iOS device. + +15. If the "codesign wants to sign using key in your keychain" dialog is displayed, click __Allow__. + +16. The project is now built, and the app is installed on your device. The first time you run the push sample app, your device will ask permission to allow push notifications. Tap OK. + +17. In the app, tap the __Send a push with Phonegap!__ button to send yourself a push notification. + +.. image:: iospgapp.png + +### About iOS provisioning profiles +For iOS app testing, you need a provisioning profile that's associated with an Apple ID. You set up the provisioning profile in the Apple developer portal, download the profile, and import it into Xcode. + +To set up a provisioning profile, you need to create an "iOS App Development" certificate in the Apple developer portal. For example, in the Apple APNs setup earlier in this tutorial, you created a certificate in the Apple developer portal to be used for push notifications. However, you won't be able to create a provisioning portal with just that certificate. You also need to create an "iOS App Development" certificate (the configuration settings don't matter), as shown in the following image. + +.. image:: iospgcert.png + +After you create an iOS App Development certificate, you can create a provisioning profile that includes your App ID/certificate for push notifications. + +### Android Dev Setup + +To configure and run the native Android push notification sample app, do the following: + +1. Make sure you have the latest Android SDK installed in your IDE, and that Android APIs have been installed via the Android SDK Manager. + +2. Import the native Android sample app project into your IDE + +3. Modify the following in __/src/com.ganyo.pushtest/Settings.java__: + +* __GCM_SENDER_ID__: Your Google Cloud Messaging (GCM) project number, as described in the Tutorial: Push notifications sample app. + +* __NOTIFIER__: Name of your notifier. (For the sample, make sure it's the name of the notifier you created.) + +* __ORG__: Your Apigee organization. + +* __APP__: The app in your organization where you created the notifier. (For the sample, make sure it's "sandbox".) + +* __USER__ and __PASSWORD__: Optional. If you created your notifier in an app other than "sandbox" (which doesn't require authentication), enter the username and password of one of your Usergrid admin users. + +4. In AndroidManifest.xml, be sure the proper Android permissions are included, such as READ_PHONE_STATE and VIBRATE. + +5. In your project properties, go to __Java Build Path > Libraries__ and add all the JAR files from the project's /libs directory. + +6. In the __Order and Export__ tab, move the JARs to the top of the list and select all the check boxes. Make sure the order and selections match the following image: + +.. image:: assettings.png + +7. If you're using an emulator, configure the emulator to use the Google APIs Level 16 target. + +.. image:: asemu.png + +8. Run the project as an Android Application. The IDE should compile the project and install the app on your device. + +9. Press the button on the app to send yourself a push notification. + +.. image:: asapp.png + +### PhoneGap Android Dev Setup + +To configure and run the PhoneGap Android push notification sample app, do the following: + +1. Make sure you have the latest Android SDK installed in your IDE, and that Android APIs have been installed via the Android SDK Manager. + +2. Import the PhoneGap Android sample app project into your IDE. + +3. Modify the following in __/assets/www/js/index.js__: + +* __orgName__: Your apigee organization. + +* __appName__: The app in your organization where you created the notifier. (For the sample, make sure it's "sandbox".) + +* __notifier__: Name of your notifier. + +* __senderID__: Your API project number (the project must support Google Cloud Messaging for Android (GCM)), as described in the [Registering with a notification service](registration.html). + +4. In __AndroidManifest.xml__, be sure the proper Android permissions are included. This includes READ_PHONE_STATE and VIBRATE. + +5. In your project properties, go to __Java Build Path > Libraries__ and add all the JAR files from the project's /libs directory. + +6. In the __Order and Export__ tab, move the JARs to the top of the list and select all the check boxes. Make sure the order and selections match the following image: + +.. image:: pgasettings.png + +7. If you're using an emulator, configure the emulator to use the Google APIs Level 16 target or above. Also, be sure to see the Android requirements in [Adding push notifications support](adding-push-supprt.html) for steps on setting up the emulator to support push notifications. + +.. image:: pgaspath.png + +8. Run the project as an Android Application. The IDE should compile the project and install the app on your device. + +9. Press the button on the app to send yourself a push notification. + +.. image:: pgaapp.png + +

Note


 +For troubleshooting tips, see [Adding push notifications support](adding-push-supprt.html. +

+ +### More about PhoneGap +The [PhoneGap](http://phonegap.com/) iOS push notification sample was created using standard web technologies such as HTML5, JavaScript, and CSS. You build the app with those technologies, and PhoneGap provides project templates for iOS, Android, and other platforms. For example, atop platform-specific PhoneGap code, core app code between the iOS and Android samples is essentially the same. + +When using PhoneGap to develop push notification apps, you use a PhoneGap plugin designed to support push notifications. That plugin is included in the Apigee samples. For more about the plugin, see the [plugin's GitHub project](https://github.com/phonegap-build/PushPlugin/blob/master/README.md). + +## Step 5: Review the data entities created by the sample app + +1. Log in to the admin portal, and select Data in the left navigation pane. + +2. Select any of the following collections to view the entities that were created in them by the push notification sample app: + +* ``/devices`` - To see the device that was added. + +* ``/notifications`` - To see the notification that was sent. + +* ``/receipts`` - To see the receipt generated from the successful push. + +## Step 6: Send additional push notifications using other Usergrid tools +Send a push notification from the Usergrid Notifications console +On the Send Notification screen. Select your notifier, select All Devices, enter a message, select Now, and click to send it. + +.. image:: sendnotification.png + +### Send a push notification directly via the push notifications API +Use the following curl command in a terminal window, replacing your-org, your-app and notifier-name. + + curl -X POST "https://api.usergrid.com/your-org/your-app/devices/*/notifications" -d '{"payloads":{"notifier-name":"I just sent another notification! Yea, me!"}}' + \ No newline at end of file diff --git a/content/docs/_sources/push-notifications/users-devices.txt b/content/docs/_sources/push-notifications/users-devices.txt new file mode 100644 index 0000000000..4b1c2b6898 --- /dev/null +++ b/content/docs/_sources/push-notifications/users-devices.txt @@ -0,0 +1,108 @@ +# Users & Devices + +Users and Devices are the primary ways to identify access to the system. Devices are great to track anonymous access, while Users allow you to model signing up, signing in, etc. + +Users +----- + +## Properties + +Property Type Description +------------ --------- --------------------------------------------------------------------------------- + uuid UUID User’s unique entity ID + type string Type of entity, in this case “user” + created long [UNIX timestamp](http://en.wikipedia.org/wiki/Unix_time) of entity creation + modified long [UNIX timestamp](http://en.wikipedia.org/wiki/Unix_time) of entity modification + username string Valid and unique string username (mandatory) + password string User password + email string Valid and unique email address + name string User display name + activated boolean Whether the user account is activated + disabled boolean Whether the user account is administratively disabled + firstname string User first name + middlename string User middle name + lastname string User last name + picture string User picture + + +## Sets + + Set Type Description + ------------- -------- --------------------------------------- + connections string Set of connection types (e.g., likes) + rolenames string Set of roles assigned to a user + permissions string Set of user permissions + credentials string Set of user credentials + +## Relationshops + + Collection Type Description + ------------ ---------- ----------------------------------------------------- + groups group Collection of groups to which a user belongs + devices device Collection of devices in the service + activities activity Collection of activities a user has performed + feed activity Inbox of activity notifications a user has received + roles role Set of roles assigned to a user + +## Facebook Sign-in + +You can authenticate your Apache Usergrid requests by logging into +Facebook. To access Apache Usergrid resources, you need to provide an +access token with each request (unless you use the sandbox app). You can +get an access token by connecting to an appropriate web service endpoint +and providing the correct client credentials — this is further described +in [Authenticating users and application +clients](/authenticating-users-and-application-clients). However, you +can also obtain an access token by logging into Facebook. + +To enable authentication to Apache Usergrid through Facebook, do the +following in your app: + +1. Make a login call to the Facebook API (do this using the [Facebook + SDK](https://developers.facebook.com/docs/sdks/) or + [API](https://developers.facebook.com/docs/facebook-login/)). If the + login succeeds, a Facebook access token is returned. +2. Send the Facebook access token to Apache Usergrid. If the Facebook + access token is valid and the user does not already exist in App + Services, Apache Usergrid provisions a new Apache Usergrid user. It also + returns an Apache Usergrid access token, which you can use for + subsequent Apache Usergrid API calls. Behind the scenes, Apache Usergrid + uses the Facebook access token to retrieve the user's profile + information from Facebook. + + If the Facebook access token is invalid, Facebook returns an OAuth + authentication error, and the login does not succeed. + +The request to authenticate to Apache Usergrid using a Facebook access +token is: + + GET https://api.usergrid.com/{my_org}/{my_app}/auth/facebook?fb_access_token={fb_access_token} + +where: + +* {my\_org} is the organization UUID or organization name.\ +* {my\_app} is the application UUID or application name.\ +* {fb\_access\_token} is the Facebook access token. + + +Devices +------- + +## Properties + +Property Type Description +---------- -------- --------------------------------------------------------------------------------- + uuid UUID Entity unique ID + type string Entity type (e.g., device) + created long [UNIX timestamp](http://en.wikipedia.org/wiki/Unix_time) of entity creation + modified long [UNIX timestamp](http://en.wikipedia.org/wiki/Unix_time) of entity modification + name string Device name (mandatory) + + +## Relationships + +Devices have the following associated collection. + + Collection Type Description + ------------ ------ ----------------------------------------------- + users user Collection of users to which a device belongs diff --git a/content/docs/_sources/reference/contribute-code.txt b/content/docs/_sources/reference/contribute-code.txt new file mode 100644 index 0000000000..ef8e9685d7 --- /dev/null +++ b/content/docs/_sources/reference/contribute-code.txt @@ -0,0 +1,37 @@ +# How to Contribute Code & Docs + +Contribute via GitHub +--- + +The Usergrid project uses GitHub as our code review system. If you want to contribute to Usergrid, then you should fork the apache/usergrid repo and submit PRs back to the project. +Here are step-by-step guides for both both external contributors and committers: + +* How to contribute code to Usergrid: [External Contributors Guide](https://cwiki.apache.org/confluence/display/usergrid/Usergrid+External+Contributors+Guide) + +* How to accept code contributions to Usergrid: [Usergrid Committers Guide](https://cwiki.apache.org/confluence/display/usergrid/Usergrid+Committers+Guide) + + +Building Usergrid +--- + +Usergrid is made up of multiple components that are built separately: + +* __Stack__: The Usergrid Stack is a Java web application, built using Maven. + * Build instructions are in the [README](https://github.com/apache/usergrid/blob/master/stack/README.md). + +* __Portal__: The Usergrid Portal is an Angular.js application and builds with Grunt. + * Build instructions are in the [README](https://github.com/apache/usergrid/blob/master/portal/README.md). + +* SDKs: See the README files in the `/sdks` sub-directories for SDK build instructions. + + +Building the Website and Documentation +--- + +Usergrid documentation source is located in the `/docs` directory of our Git repo, written in [Markdown](https://daringfireball.net/projects/markdown/) format and managed by the [Sphinx](http://www.sphinx-doc.org) documentation system. For more information: + +* [Apache Usergrid Documentation build instructions](https://github.com/apache/usergrid/blob/master/docs/README.md) + +The Usergrid website source is managed in the `/website` directory. We use the [Nanoc](http://nanoc.ws) static-site generator to generate website content from source. For more information: + +* [Apache User Website build instructions](https://github.com/apache/usergrid/blob/master/website/README.md) diff --git a/content/docs/_sources/reference/presos-and-videos.txt b/content/docs/_sources/reference/presos-and-videos.txt new file mode 100644 index 0000000000..2112d110a9 --- /dev/null +++ b/content/docs/_sources/reference/presos-and-videos.txt @@ -0,0 +1,31 @@ +# Presentations & Videos + +## Building Mobile Apps with Apache Usergrid +- Screen-cast of a talk given by Dave Johnson at the All Things Open 2014, Raleigh, NC. + + + +## How to Contribute to Apache Usergrid +- David Johnson at [ApacheCon NA 2014](http://apacheconnorthamerica2014.sched.org/event/29971aabd3c86398be2ae93403c7d1d2) + + + +## Apache Usergrid Internals +- Sungju Jin + + + +## Open Source Mobile Backend on Cassandra +- Ed Anuff + + + +## Usergrid Overview +- Ed Anuff + + \ No newline at end of file diff --git a/content/docs/_sources/rest-endpoints/api-docs.txt b/content/docs/_sources/rest-endpoints/api-docs.txt new file mode 100644 index 0000000000..25e820a55d --- /dev/null +++ b/content/docs/_sources/rest-endpoints/api-docs.txt @@ -0,0 +1,3977 @@ +

Usergrid API Reference

+ +Methods are organized by tag. Follow the methods are the [Model Definitions](#models). + +

Table of Contents

+ +* [Access-Tokens](#access-tokens) +* [Activities](#activities) +* [Admin-Users](#admin-users) +* [App-Users](#app-users) +* [Entities-Collections](#entities-collections) +* [Events](#events) +* [Groups](#groups) +* [Notifications](#notifications) +* [Organizations-Applications](#organizations-applications) +* [Permissions-Roles](#permissions-roles) + +
+
+ + +## Methods + + +### Access-Tokens + + +

POST /management/token

+ + + +Login with Admin-User or Organization credentials. + +

Parameters

+ +* __login-credentials__ ([LoginCredentials](#logincredentials)) +Login credentials either username/password or id/secret. (Specified in body). + +

Responses

+ +__200__ + +* Description: Object containing access_token. +* Schema: [AccessTokenResponse](#accesstokenresponse) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{appId}/token

+ + + +Login with App-User or Application credentials. + +

Parameters

+ +* __login-credentials__ ([LoginCredentials](#logincredentials)) +Login credentials either username/password or id/secret. (Specified in body). + +

Responses

+ +__200__ + +* Description: Object containing access_token. +* Schema: [AccessTokenResponse](#accesstokenresponse) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +### Activities + + +

GET /{orgId}/{appId}/groups/{groupId}/feed

+ + + +Get a group's feed through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __groupId__ (string) +One of the group's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of group's activity. +* Schema: [ActivityFeed](#activityfeed) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{appId}/users/{userId}/activities

+ + + +Create an activity in the activities collection. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __userId-3__ (string) +One of the user's identification which includes username or UUID. (Specified in path). +* __CreateActivity__ ([CreateActivity](#createactivity)) +One or more sets of activity properties. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of user's activity. +* Schema: [ActivityFeed](#activityfeed) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{appId}/users/{userId}/feed

+ + + +Retrieve a user's feed through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __userId-3__ (string) +One of the user's identification which includes username or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of user's activity feed. +* Schema: [ActivityFeed](#activityfeed) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +### Admin-Users + + +

GET /management/orgs/{orgId}/users

+ + + +Retrieve details about the admin users in an organization. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved Admin user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

DELETE /management/orgs/{orgId}/users/{userId}

+ + + +Remove an admin user from an organization through providing both Id of application and organization. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __userId-2__ (string) +One of the user's identification which includes username, email address or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of deleted Admin user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /management/users

+ + + +Create a whole new admin user. + +

Parameters

+ +* __CreateAdminUser__ ([CreateAdminUser](#createadminuser)) +User entity with fields required for User creation. (Specified in body). + +

Responses

+ +__200__ + +* Description: An API Response with a entities array containing the newly created Admin User. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/users/resetpw

+ + + +Initiate the reset of an admin user's password. + +

Parameters

+ + +

Responses

+ +__200__ + +* Description: An array of complete messages. +* Schema: [Action](#action) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /management/users/resetpw

+ + + +Complete the password reset through getting the newpassword and the old one for identification. + +

Parameters

+ +* __ResetPWMsg__ ([ResetPWMsg](#resetpwmsg)) +Parameters and value for the Captcha challenge, the admin user's response to the Captcha challenge, and the admin user's email address. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of complete messages. +* Schema: [](#) + +__default__ + +* Description: +* Schema: [Error](#error) + + +

GET /management/users/{userId}

+ + + +Retrieve details about an admin user. + +

Parameters

+ +* __userId__ (string) +One of the user's identification which includes username, real name, email address or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An API Response with a entities array containing the Admin User. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

PUT /management/users/{userId}

+ + + +Update the info of an admin user. + +

Parameters

+ +* __userId__ (string) +One of the user's identification which includes username, real name, email address or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An API Response with a entities array containing the updated Admin User +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/users/{userId}/activate

+ + + +Activate an admin user from a link provIded in an email notification. + +

Parameters

+ +* __userId__ (string) +One of the user's identification which includes username, real name, email address or UUID. (Specified in path). +* __token__ (string) +Activation token's query statement. (Specified in query). +* __confirm_email__ (boolean) +Query statement of whether send confimation email or not. (Specified in query). + +

Responses

+ +__200__ + +* Description: An array of complete messages. +* Schema: [Action](#action) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

PUT /management/users/{userId}/password

+ + + +Update an admin user's password through getting the newpassword and the old one for identification. + +

Parameters

+ +* __userId__ (string) +One of the user's identification which includes username, real name, email address or UUID. (Specified in path). +* __ResetPW__ ([ResetPW](#resetpw)) +The user's old and new password. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of complete messages. +* Schema: [Action](#action) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/users/{userId}/reactivate

+ + + +Reactivate an expired admin user. + +

Parameters

+ +* __userId__ (string) +One of the user's identification which includes username, real name, email address or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of complete messages. +* Schema: [Action](#action) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +### App-Users + + +

GET /{orgId}/{appId}/users

+ + + +Retrieve users though query statement. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __queryStatement__ (string) +The query statement of the User. (Specified in query). + +

Responses

+ +__200__ + +* Description: An array of retrieved user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{appId}/users

+ + + +Create a user in the users collection through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __CreateUser__ ([CreateUser](#createuser)) +The properties of the user. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of created user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{appId}/users/{userId}

+ + + +Retrieve a user through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __userId-2__ (string) +One of the user's identification which includes username, email address or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

PUT /{orgId}/{appId}/users/{userId}

+ + + +Update a user through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __userId-3__ (string) +One of the user's identification which includes username or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of updated user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

DELETE /{orgId}/{appId}/users/{userId}

+ + + +Remove a user through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __userId-3__ (string) +One of the user's identification which includes username or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of deleted user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{appId}/users/{user}/password

+ + + +Set a user's password or reset the user's existing password. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __username__ (string) +The username of the user. (Specified in path). +* __ResetPW__ ([ResetPW](#resetpw)) +The user's old and new password. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of complete messages. +* Schema: [Action](#action) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +### Entities-Collections + + +

GET /{orgId}/{appId}/users/{userId}/{relation}

+ + + +Retrieve a user's collections or connections through query statement. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __userId-3__ (string) +One of the user's identification which includes username or UUID. (Specified in path). +* __relation__ (string) +The relation between user and collections. (Specified in path). +* __queryStatement__ (string) +The query statement of the user. (Specified in query). + +

Responses

+ +__200__ + +* Description: An array of user's collections info. +* Schema: [Entity](#entity) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{appId}/{collectionId}

+ + + +Retrieve collection through query statement. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __collectionId__ (string) +One of the collection's identification which includes name or uuid. (Specified in path). +* __queryStatement__ (string) +Any values specified in the query statement should be enclosed in single-quotes. (Specified in query). + +

Responses

+ +__200__ + +* Description: An array of retrieved collection's info. +* Schema: [Entity](#entity) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

PUT /{orgId}/{appId}/{collectionId}

+ + + +Update collection through query statement. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __collectionId__ (string) +One of the collection's identification which includes name or uuid. (Specified in path). +* __queryStatement__ (string) +Any values specified in the query statement should be enclosed in single-quotes. (Specified in query). + +

Responses

+ +__200__ + +* Description: An array of updated collection's info. +* Schema: [Entity](#entity) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{appId}/{collectionId}/{entityId1}/{relation}/{entityId2}

+ + + +Add an entity to a collection through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __collectionId__ (string) +One of the collection's identification which includes name or uuid. (Specified in path). +* __entityId1__ (string) +The Id of the 1st entity. (Specified in path). +* __relation__ (string) +The relation between 1st entity and 2nd entity. (Specified in path). +* __entityId2__ (string) +The Id of the 2nd entity. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of added entity's info. +* Schema: [Entity](#entity) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

DELETE /{orgId}/{appId}/{collectionId}/{entityId1}/{relation}/{entityId2}

+ + + +Remove an entity from a collection through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __collectionId__ (string) +One of the collection's identification which includes name or uuid. (Specified in path). +* __entityId1__ (string) +The Id of the 1st entity. (Specified in path). +* __relation__ (string) +The relation between 1st entity and 2nd entity. (Specified in path). +* __entityId2__ (string) +The Id of the 2nd entity. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of deleted entity's info. +* Schema: [Entity](#entity) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{appId}/{collectionId}/{entityId}

+ + + +Retrieve an entity through providing Id of application, organization, collection and entity. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __collectionId__ (string) +One of the collection's identification which includes name or uuid. (Specified in path). +* __entityId__ (string) +One of the entity's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved entity's info. +* Schema: [Entity](#entity) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

PUT /{orgId}/{appId}/{collectionId}/{entityId}

+ + + +One or more properties can be updated with a single request. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __collectionId__ (string) +One of the collection's identification which includes name or uuid. (Specified in path). +* __entityId__ (string) +One of the entity's identification which includes name or uuid. (Specified in path). +* __entityproperty__ ([CreateEntities](#createentities)) +The properties of the entity. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of updated entity's info. +* Schema: [Entity](#entity) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

DELETE /{orgId}/{appId}/{collectionId}/{entityId}

+ + + +Delete an entity from the collection. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __collectionId__ (string) +One of the collection's identification which includes name or uuid. (Specified in path). +* __entityId__ (string) +One of the entity's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of deleted entity's info. +* Schema: [Entity](#entity) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{appId}/{entitytype}

+ + + +When a new entity is created, Usergrid will automatically create a corresponding collection if one does not already exist. The collection will automatically be named with the plural form of the entity type. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __entitytype__ (string) +The entity type to create. (Specified in path). +* __entityproperty__ ([CreateEntities](#createentities)) +The properties of the entity. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of created custom entity's info. +* Schema: [Entity](#entity) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +### Events + + +

POST /{orgId}/{appId}/events

+ + + +Create an event through providing both Id of organization and application. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __CreateEvent__ ([CreateEvent](#createevent)) +The required property of the event. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of created event's info. +* Schema: [Event](#event) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +### Groups + + +

POST /{orgId}/{appId}/groups

+ + + +Create a new group through providing both Id of organization and application. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __groupproperty__ ([CreateGroup](#creategroup)) +The property of the created group. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of created group's info. +* Schema: [Group](#group) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{appId}/groups/{groupId}/activities

+ + + +Create an activity to a specific group. In this case the activity is created in the activities collection and is accessible at the /activities endpoint to users who have the permission to read that endpoint. In addition, a relationship is established between the activity and the group, and because of that, the activity will appear in the group’s feed. The group 'owns' the activity. Also, the activity will be published in the feed of all users that are members of the group. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __groupId__ (string) +One of the group's identification which includes name or uuid. (Specified in path). +* __CreateActivity__ ([CreateActivity](#createactivity)) +One or more sets of activity properties. (Specified in body). + +

Responses

+ +__200__ + +* Description: +* Schema: [ActivityFeed](#activityfeed) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{appId}/groups/{groupId}/users/{userId}

+ + + +Add a user to a group through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __groupId__ (string) +One of the group's identification which includes name or uuid. (Specified in path). +* __userId-3__ (string) +One of the user's identification which includes username or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of added user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

DELETE /{orgId}/{appId}/groups/{groupId}/users/{userId}

+ + + +Delete user from a group through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __groupId__ (string) +One of the group's identification which includes name or uuid. (Specified in path). +* __userId-3__ (string) +One of the user's identification which includes username or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of deleted user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{org_Id}/{app_Id}/groups/{groupId}

+ + + +Get a group through through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __groupId__ (string) +One of the group's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved group's info. +* Schema: [Group](#group) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

PUT /{org_Id}/{app_Id}/groups/{groupId}

+ + + +Update a group through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __groupId__ (string) +One of the group's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of updated group's info. +* Schema: [Group](#group) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +### Notifications + + +

POST /{orgId}/{applicationId}/devices

+ + + +Create notifications for user through targeting by location and providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). +* __notification__ ([CreateNotifications](#createnotifications)) +These parameters are used when forming the notification portion of the request. (Specified in body). +* __queryStatement__ (string) +The query statement of the location of the user. (Specified in query). + +

Responses

+ +__200__ + +* Description: An array of created notification's info. +* Schema: [Notification](#notification) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{applicationId}/devices/*/notifications

+ + + +Create notifications for all devices. This request will target all device entities. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). +* __notification__ ([CreateNotifications](#createnotifications)) +These parameters are used when forming the notification portion of the request. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of created notification's info. +* Schema: [Notification](#notification) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{applicationId}/devices/{deviceId}/notifications

+ + + +Create notifications for a single device. This request will target a specific device entity. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). +* __deviceId__ (string) +One of the device's identification which includes name or uuid. (Specified in path). +* __notification__ ([CreateNotifications](#createnotifications)) +These parameters are used when forming the notification portion of the request. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of created notification's info. +* Schema: [Notification](#notification) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{applicationId}/groups/{path}/notifications

+ + + +Create notifications for a group. This request will target all users associated with a specific group entity. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __path__ (string) +The path of the group. (Specified in path). +* __notification__ ([CreateNotifications](#createnotifications)) +These parameters are used when forming the notification portion of the request. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of created notification's info. +* Schema: [Notification](#notification) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{applicationId}/notifications

+ + + +Retrieve one or more notifications through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved notification's info. +* Schema: [Notification](#notification) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

PUT /{orgId}/{applicationId}/notifications/{notificationId}

+ + + +Update a Notification in order to cancel the notifcation or set a new expiration time. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). +* __notificationId__ (string) +One of the notification's identification which includes name or uuid. (Specified in path). +* __notificationUpdate__ ([NotificationUpdate](#notificationupdate)) +Object with Notification fields to be updated. (Specified in body). + +

Responses

+ +__200__ + +* Description: An API Response object containing an entity of type Notification. +* Schema: [Notification](#notification) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

DELETE /{orgId}/{applicationId}/notifications/{notificationId}

+ + + +Delete an unsent Notification from the system. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). +* __notificationId__ (string) +One of the notification's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: API Response containing Notification entity that was deleted. +* Schema: [Notification](#notification) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{applicationId}/receipts

+ + + +Retrieve one or more receipts through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved receipt's info. +* Schema: [Receipt](#receipt) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{applicationId}/users/{userId}/notifications

+ + + +Create notifications for a user. This request will target a specific user entity. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). +* __userId-3__ (string) +One of the user's identification which includes username or UUID. (Specified in path). +* __notification__ ([CreateNotifications](#createnotifications)) +These parameters are used when forming the notification portion of the request. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of created notification's info. +* Schema: [Notification](#notification) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{applicationId}/{deviceId}/*/receipts

+ + + +Retrieve receipts associated with one or more devices through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). +* __deviceId__ (string) +One of the device's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved receipt's info. +* Schema: [Receipt](#receipt) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{applicationId}/{notificationId}/*/queue

+ + + +Retrieve the list of devices associated with one or more notifications before the notifications are sent through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). +* __notificationId__ (string) +One of the notification's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved device's info. +* Schema: [Device](#device) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{applicationId}/{notificationId}/*/receipts

+ + + +Retrieve receipts for one or more notifications through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). +* __notificationId__ (string) +One of the notification's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved receipt's info. +* Schema: [Receipt](#receipt) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{applicationId}/{receiptId}/*/notifications

+ + + +Retrieve notifications associated with one or more receipts through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __applicationId__ (string) +One of the application's identification which includes name or uuid (same as appId). (Specified in path). +* __receiptId__ (string) +One of the receipt's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved notification's info. +* Schema: [Notification](#notification) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +### Organizations-Applications + + +

POST /management/orgs

+ + + +Create an organization through a form post. + +

Parameters

+ +* __CreateOrg__ ([CreateOrg](#createorg)) +A set of organization properties supplied through a form. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of created Organization. +* Schema: [Organization](#organization) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/orgs/{orgId}

+ + + +Retrieve an organization given a specified UUID or username. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of created Organization. +* Schema: [Organization](#organization) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/orgs/{orgId}/activate

+ + + +Activate an organization from a link provIded in an email notification. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __token__ (string) +Activation token. (Specified in query). +* __confirm_email__ (boolean) +Send confirmation email or not. (Specified in query). + +

Responses

+ +__200__ + +* Description: An array of complete messages. +* Schema: [Action](#action) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/orgs/{orgId}/apps

+ + + +Retrieve the applications in an organization through providing both Id of application and organization. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved application data. +* Schema: [AppData](#appdata) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

DELETE /management/orgs/{orgId}/apps/{appId}

+ + + +Remove an application from an organization through providing both Id of application and organization. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of deleted application info. +* Schema: [AppData](#appdata) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/orgs/{orgId}/apps/{appId}/credentials

+ + + +Retrieve the client Id and client secret credentials for an application in an organization. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved credentials info. +* Schema: [Credential](#credential) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /management/orgs/{orgId}/apps/{appId}/credentials

+ + + +Generate the client Id and client secret credentials for an application in an organization. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of generated credentials info. +* Schema: [Credential](#credential) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/orgs/{orgId}/credentials

+ + + +Retrieve the credentials for an organization client. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of Credential +* Schema: [Credential](#credential) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /management/orgs/{orgId}/credentials

+ + + +Generate whole new credentials for an organization client. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of Credential +* Schema: [Credential](#credential) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/orgs/{orgId}/feed

+ + + +Retrieve an organization's activity feed. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of the organization's ActivityFeed. +* Schema: [ActivityFeed](#activityfeed) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/orgs/{orgId}/reactivate

+ + + +Reactivate an expired organization. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of complete messages. +* Schema: [Action](#action) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /management/users/{userId}/feed

+ + + +Retrieve an admin user's activity feed. + +

Parameters

+ +* __userId__ (string) +One of the user's identification which includes username, real name, email address or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of user's activity +* Schema: [ActivityFeed](#activityfeed) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +### Permissions-Roles + + +

GET /{orgId}/{appId}/roles

+ + + +Retrieve the roles in an application through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of retrieved role's info. +* Schema: [Role](#role) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{appId}/roles

+ + + +Create a new role through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __roleproperty__ ([AddRole](#addrole)) +The required properties of the role. (Specified in body). + +

Responses

+ +__200__ + +* Description: An array of created role's info. +* Schema: [Role](#role) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

DELETE /{orgId}/{appId}/roles/{roleId}/permissions

+ + + +Remove permissions from a role. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __roleId__ (string) +One of the role's identification which includes name or uuid. (Specified in path). +* __Permissions__ ([Permissions](#permissions)) +The query statement of the url pattern. (Specified in body). + +

Responses

+ +__200__ + +* Description: Permissions object with array of the deleated Usergrid Permission strings. +* Schema: [Permissions](#permissions) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{appId}/roles/{roleId}/users

+ + + +Retrieve the users in a role through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __roleId__ (string) +One of the role's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: An API Response with a entities array of Users. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{appId}/roles/{roleId}/users/{userId}

+ + + +Add a user to a role through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __roleId__ (string) +One of the role's identification which includes name or uuid. (Specified in path). +* __userId-3__ (string) +One of the user's identification which includes username or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of added user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

DELETE /{orgId}/{appId}/roles/{roleId}/users/{userId}

+ + + +Remove a user from a role through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __roleId__ (string) +One of the role's identification which includes name or uuid. (Specified in path). +* __userId-3__ (string) +One of the user's identification which includes username or UUID. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of deleted user's info. +* Schema: [User](#user) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

DELETE /{orgId}/{appId}/roles/{rolename}

+ + + +Remove a role through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __rolename__ (string) +The name of the role. (Specified in path). + +

Responses

+ +__200__ + +* Description: An array of deleted role's info. +* Schema: [Role](#role) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

GET /{orgId}/{applicationId}/roles/{roleId}/permissions

+ + + +Retrieve permissions for a Role. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __roleId__ (string) +One of the role's identification which includes name or uuid. (Specified in path). + +

Responses

+ +__200__ + +* Description: Permissions object with array of Usergrid Permission strings. +* Schema: [Permissions](#permissions) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +

POST /{orgId}/{applicationId}/roles/{roleId}/permissions

+ + + +Add permissions to a role through providing all the identifications. + +

Parameters

+ +* __orgId__ (string) +One of the organization's identification which includes name or uuid. (Specified in path). +* __appId__ (string) +One of the application's identification which includes name or uuid. (Specified in path). +* __roleId__ (string) +One of the role's identification which includes name or uuid. (Specified in path). +* __Permissions__ ([Permissions](#permissions)) +Permissions object with array of Usergrid Permission strings to be added. (Specified in body). + +

Responses

+ +__200__ + +* Description: Permissions object with array of Usergrid Permission strings. +* Schema: [Permission](#permission) + +__default__ + +* Description: Unexpected error. +* Schema: [Error](#error) + + +## Models +This section lists the properties for the Usergrid Default Entities: + +### AccessTokenResponse + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
access_token + string + Access-token that may be used on subsequent requests.false
expires_in + number + Time (in milliseconds) until access-token expires.false
user + [User](#user) + User object if login was done as a user.false
+ + +### Action + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
action + string + The requested action.false
status + string + The status of the requested action.false
timestamp + number + The timestamp of the requested action.false
duration + number + The duration of the requested action.false
token + string + The token required for getting an AdminUser.false
+ +__Referring Definitions__ + +* [Receipt](#receipt) +* [Device](#device) +* [Notification](#notification) +* [Role](#role) +* [Event](#event) +* [Group](#group) +* [Credential](#credential) +* [Organization](#organization) +* [AppData](#appdata) +* [User](#user) +* [ActivityFeed](#activityfeed) + + +### ActivityFeed + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
entityproperty + [Entity](#entity) + false
category + string + The category of the activity.false
metadataproperty + [Metadata](#metadata) + false
objectproperty + [Object](#object) + false
title + string + The title of the activity.false
verb + string + The verb of the activity.false
published + number + UTC timestamp of the feed publish time.false
completeMsg + [Action](#action) + false
+ + +### AddRole + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
title + string + The title of the role.true
role name + string + The name of the role.true
+ + +### AppData + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
tester/sandbox + string + The UUID of tester/sandbox.false
tester/app1 + string + The UUID of tester/app1.false
tester/app2 + string + The UUID of tester/app2.false
completeMsg + [Action](#action) + false
+ +__Referring Definitions__ + +* [Organization](#organization) + + +### CreateActivity + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
displayName + string + true
uuid + string + true
username + string + true
image + [ImageModel](#imagemodel) + false
verb + string + true
content + string + true
+ + +### CreateAdminUser + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
username + string + true
email + string + false
name + string + false
password + string + false
+ + +### CreateEntities + + + +__Properties__ + + + + + + + + +
NameTypeDescriptionRequired
+ + +### CreateEvent + + + +__Properties__ + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
timestamp + string + true
+ + +### CreateGroup + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
title + string + The title of the group.true
path + string + The path of the group.true
+ + +### CreateNotifications + +An array of Notifications to be created. + +__Properties__ + + + + + + + + +
NameTypeDescriptionRequired
+ + +### CreateOrg + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
organization + string + true
username + string + true
name + string + true
email + string + true
password + string + true
+ + +### CreateUser + + + +__Properties__ + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
username + string + true
+ + +### Credential + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
client_Id + string + The Id of the client.false
client_secret + string + The secret of the client.false
completeMsg + [Action](#action) + false
+ + +### Device + +Represents a single Device that is registered for recieving of Push Notifications. + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuid + string + Unique entity Id.false
type + string + Type of entity.false
name + string + Notifier display name.false
created + number + UTC timestamp in milliseconds of when the entity was created.false
modified + number + UTC timestamp in milliseconds of when the entity was last modified.false
metadata + [Metadata](#metadata) + false
completeMsg + [Action](#action) + false
+ + +### Entity + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuid + string + The UUID of the entity.false
type + string + The type of the entity.false
created + number + UTC timestamp of entity creation time.false
modified + [Actor](#actor) + UTC timestamp of entity modified time.false
metadata + [Metadata](#metadata) + false
name + string + The name of the entity.false
message + string + false
+ +__Referring Definitions__ + +* [Role](#role) +* [Event](#event) +* [ActivityFeed](#activityfeed) + + +### Error + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
code + integer + false
message + string + false
fields + object + false
+ + +### Event + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
applicationName + string + The application name of the event.false
entity + [Entity](#entity) + false
url + string + The url of the event.false
applicationId + string + The application UUID of the event.false
parameters + string + The parameters of the event.false
organization + string + The title of the organization.false
completeMsg + [Action](#action) + false
+ + +### Group + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuid + string + The UUID of the group.false
type + string + The type of the group.false
created + string + The created Id for the group.false
modified + string + The modified Id for the group.false
path + string + The path of the group.false
metadata + [Metadata](#metadata) + false
title + string + The title of the group.false
completeMsg + [Action](#action) + false
+ + +### LoginCredentials + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
grant_type + string + Grant-type must be 'password' or 'client_credentials'.false
username + string + Username of user attempting login, required only if grant_type is 'password'.false
password + string + Password of user attempting login, required only if grant_type is 'password'.false
client_id + string + Client-ID portion of credentials, required only if grant_type is 'client_credentials'.false
client_secret + string + Client-Secret portion of credentials, required only if grant_type is 'client_credentials'.false
+ + +### Notification + +Represents a Push Notification that is either scheduled, finished or cancelled. + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuid + string + Unique entity Id.false
type + string + Type of entity.false
created + number + UTC timestamp in milliseconds of when the entity was created.false
modified + number + UTC timestamp in milliseconds of when the entity was last modified.false
payloads + string + The push notifications to be delivered.true
errorMessage + string + Error message returned by the notification service (APNs or GCM) if the notification fails entirely.false
scheduled + boolean + Whether the notification is currently scheduled for delivery.false
state + string + The current delivery status of the notification 'FINISHED', 'SCHEDULED' or 'CANCELED'.false
metadata + [Metadata](#metadata) + false
completeMsg + [Action](#action) + false
+ + +### NotificationUpdate + +Represents fields that may be updated on a Notification to cause changes in Push Notification processing. + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
canceled + boolean + Setting this field to true will cancel a Notification, if it has not yet been sent.false
deliver + number + Specifies the UNIX timestamp time at which the Notification should be sent.false
expired + number + Specifies the UNIX timestamp time at which this Notification has expired.false
+ + +### Organization + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
applicationId + string + The application Id of the owner.false
username + string + The username of the owner.false
name + string + The name of the owner.false
email + string + The email of the owner.false
activated + boolean + Indicate whether the account is activated or not.false
disabled + boolean + Indicate whether the account is disabled or not.false
uuid + string + The UUID of the owner.false
adminUser + boolean + Indicate whether the use is a adminUser or not.false
displayEmail + string + The display of the email of the owner.false
htmldisplayEmail + string + The HTML display of the email of the owner.false
orgname + string + The name of the organization.false
orguuId + string + The UUID of the organization.false
applicationdata + [AppData](#appdata) + false
completeMsg + [Action](#action) + false
+ + +### Permissions + +Represents a set of Permissions associated with a User or a Role, each being a Usergrid Permission String. + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
application + string + The UUID of the associated application.false
applicationName + string + The name of the associated application.false
organization + string + The name of the associated organization.false
data + array + Array of strings each being a Usergrid Permission String.true
+ + +### Receipt + +Represents response received from Notification service indicating success or failure. + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuid + string + Unique entity Id.false
type + string + Type of entity.false
created + number + UTC timestamp in milliseconds of when the entity was created.false
modified + number + UTC timestamp in milliseconds of when the entity was last modified.false
payloads + string + The push notifications to be delivered.false
errorMessage + string + Error message returned by the notification service (APNs or GCM) if the notification fails entirely.false
errorCode + string + Error code returned by the notification service.false
sent + number + UTC timestamp in milliseconds for when the notification was sent.false
metadata + [Metadata](#metadata) + false
completeMsg + [Action](#action) + false
+ + +### ResetPW + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
password + string + true
newpassword + string + true
+ + +### ResetPWMsg + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
recaptcha_response + string + Parameters and value for the Captcha challenge.true
recaptcha_challenge + string + The admin user's response to the Captcha challenge.true
email + string + true
+ + +### Role + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
applicationName + string + The application name of the event.false
count + number + The numebr of the roles.false
entity + [Entity](#entity) + false
url + string + The url of the event.false
applicationId + string + The application UUID of the event.false
parameters + string + The parameters of the event.false
organization + string + The title of the organization.false
completeMsg + [Action](#action) + false
path + string + The path of the role.false
+ + +### User + +Represents a User account which may be a user within an Application's User collection, or may be an Admin User. + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
applicationId + string + The application Id of a user.false
username + string + The username of a user.false
name + string + The name of a user.false
email + string + The email of a user.false
activated + boolean + Indicate whether the account is activated or not.false
disabled + boolean + Indicate whether the account is disabled or not.false
uuid + string + The UUID of a user.false
adminUser + boolean + Indicate whether the use is a adminUser or not.false
displayEmail + string + The display of the email of a user.false
htmldisplayEmail + string + The HTML display of the email of a user.false
organization + string + The organization of the user.false
picture + string + The uri of the user's picture.false
uri + string + The uri of the user.false
path + string + The path of the user.false
completeMsg + [Action](#action) + false
+ +__Referring Definitions__ + +* [AccessTokenResponse](#accesstokenresponse) + + +## Sub-Types +This section lists the properties for sub-types used in Usergrid Default Entities. + +### Collections + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
activities + string + false
feed + string + false
roles + string + false
users + string + false
+ +__Referring Definitions__ + +* [Metadata](#metadata) + + +### ImageModel + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
duration + number + false
height + number + false
url + string + false
wIdth + integer + false
email + string + false
+ +__Referring Definitions__ + +* [CreateActivity](#createactivity) + + +### Metadata + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
cursor + string + The cursor of the metadata.false
path + string + The path of the metadata.false
sets + [Sets](#sets) + false
collections + [Collections](#collections) + false
+ +__Referring Definitions__ + +* [Receipt](#receipt) +* [Device](#device) +* [Notification](#notification) +* [Notifier](#notifier) +* [Group](#group) +* [Entity](#entity) +* [ActivityFeed](#activityfeed) + + +### Object + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
displayname + string + The display of the name of the object.false
objecttype + string + The type of the object.false
objectuuId + string + The UUID of the object.false
entitytype + string + The entitytype of the object.false
+ +__Referring Definitions__ + +* [ActivityFeed](#activityfeed) + + +### Sets + + + +__Properties__ + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
rolenames + string + false
permissions + string + false
+ +__Referring Definitions__ + +* [Metadata](#metadata) + diff --git a/content/docs/_sources/sdks/ios-new.txt b/content/docs/_sources/sdks/ios-new.txt new file mode 100644 index 0000000000..0f5b3fe9d9 --- /dev/null +++ b/content/docs/_sources/sdks/ios-new.txt @@ -0,0 +1,982 @@ +# Usergrid iOS SDK + +## Getting Started + +### Installing the SDK +### Building from Source + +# Usergrid SDK Reference with Examples + +The 66 topics listed below are each documented in the Usergrid documentation and +for each the docs provide an API reference and example for each of these clients: +curl, iOS, Android, JavaScript, Ruby and Node.js. + +## Working with Collections + +### 1. Creating collections + +SDK Method + + (ApigeeClientResponse *)apiRequest: (NSString *)url operation:(NSString *)op data:(NSString *)opData + +Parameters + +Parameter Description +--------- ----------- +url A fully-formed url in the following format: https://api.usergrid.com/// +op The HTTP method - in this case, 'POST' +opData No data is being sent, so the value is nil + +Example Request/Response + +Request: + + -(NSString*)createCollection { + + NSString *url = @"https://api.usergrid.com/your-org/your-app/items"; + NSString *op = @"POST"; + NSString *opData = nil; + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate]; + + //call createEntity to initiate the API call + ApigeeClientResponse *response = [appDelegate.dataClient apiRequest: url operation: op data: opData]; + + @try { + //success + } + @catch (NSException * e) { + //fail + } + + } + +Response: + + { + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ ], + "timestamp" : 1378857079220, + "duration" : 31, + "organization" : "your-org", + "applicationName" : "your-app" + } + +### 2. Retrieving collections + +SDK Method + + (ApigeeCollection*)getCollection:(NSString*)type + +Parameters + +Parameter Description +--------- ----------- +type The entity type associated with the collection to be retrieved + +Example Request/Response + +Request: + + -(NSString*)getCollection { + + //specify the entity type that corresponds to the collection to be retrieved + NSString *type = @"item"; + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate]; + + //Call getCollection: to initiate the API GET request + ApigeeCollection *collection = [appDelegate.dataClient getCollection:@"book"]; + } + +Response: + + { + "action" : "get", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "type" : "item", + "name" : "milk", + "created" : 1378405020796, + "modified" : 1378405020796, + "metadata" : { + "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4" + }, + "name" : "milk", + "price" : "3.25" + }, { + "uuid" : "1a9356ba-1682-11e3-a72a-81581bbaf055", + "type" : "item", + "name" : "bread", + "created" : 1378423379867, + "modified" : 1378423379867, + "metadata" : { + "path" : "/items/1a9356ba-1682-11e3-a72a-81581bbaf055" + }, + "name" : "bread", + "price" : "2.50" + } ], + "timestamp" : 1378426821261, + "duration" : 35, + "organization" : "your-org", + "applicationName" : "your-app", + "count" : 2 + } + +### 3. Updating collections + +SDK Method +(ApigeeClientResponse *)apiRequest: (NSString *)url operation:(NSString *)op data:(NSString *)opData +Properties +Parameter Description +url A fully-formed request url in the following format: +https://api.usergrid.com////?ql= +Note that you must include an empty '?ql=' query string at the end of the URL + +op The HTTP method - in this case, 'PUT' +opData A JSON-formatted string that contains the entity properties to be updated +Example Request/Response +Show Code +Request: +-(NSString*)updateCollection { + + NSString *url = @"https://api.usergrid.com/your-org/your-app/items/?ql"; + NSString *op = @"PUT"; + NSString *opData = @"{\"availability\":\"in-stock\"}"; //we escape the quotes + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; + + //call apiRequest to initiate the API call + ApigeeClientResponse *response = [appDelegate.dataClient apiRequest: url operation: op data: opData]; + + @try { + //success + } + @catch (NSException * e) { + //fail + } + +} + +Response: +{ + "action" : "put", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { + "ql" : [ "" ] + }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "31847b9a-1a62-11e3-be04-8d05e96f700d", + "type" : "item", + "name" : "milk", + "price" : "3.25", + "availability" : "in-stock" + "created" : 1378849479113, + "modified" : 1378849567301, + "name" : "milk", + }, { + "uuid" : "3192ac6a-1a62-11e3-a24f-496ca1d42ce7", + "type" : "item", + "name" : "bread", + "price" : "4.00", + "availability" : "in-stock" + "created" : 1378849479206, + "modified" : 1378849567351, + "name" : "bread", + } ], + "timestamp" : 1378849567280, + "duration" : 207, + "organization" : "your-org", + "applicationName" : "your-app" +} + +### 4. Deleting collections + +SDK Method +(ApigeeClientResponse *)apiRequest: (NSString *)url operation:(NSString *)op data:(NSString *)opData +Properties +Parameter Description +url A fully-formed url in the following format: +https://api.usergrid.com////?ql= +Note that you must include an empty '?ql=' query string at the end of the URL + +op The HTTP method - in this case, 'DELETE' +opData No data is being sent, so the value is nil +Example Request/Response +The following example will delete the first 5 entities in a collection. + +Show Code +Request: +-(NSString*)deleteCollection { + + NSString *url = @"https://api.usergrid.com/your-org/your-app/items/?ql='limit=5'"; + NSString *op = @"DELETE"; + NSString *opData = nil; + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; + + //call createEntity to initiate the API call + ApigeeClientResponse *response = [appDelegate.dataClient apiRequest: url operation: op data: opData]; + + @try { + //success + } + @catch (NSException * e) { + //fail + } + +} + +Response: +{ + "action" : "delete", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { + "ql" : [ "" ] + }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "53fe3700-0abe-11e3-b1f7-1bd100b8059e", + "type" : "item", + "name" : "milk", + "price" : "3.25", + "created" : 1377129832047, + "modified" : 1377129832047, + "metadata" : { + "path" : "/items/53fe3700-0abe-11e3-b1f7-1bd100b8059e" + }, + "name" : "milk" + }, { + "uuid" : "5ae1fa7a-0abe-11e3-89ab-6be0003c809b", + "type" : "item", + "name" : "bread", + "price" : "4.00", + "created" : 1377129843607, + "modified" : 1377129843607, + "metadata" : { + "path" : "/items/5ae1fa7a-0abe-11e3-89ab-6be0003c809b" + }, + "name" : "bread" + } ], + "timestamp" : 1378848117272, + "duration" : 12275, + "organization" : "your-org", + "applicationName" : "your-app" +} + +## Working with Entities + +### 5. Creating a custom entity + +SDK Method +(ApigeeClientResponse *)createEntity:(NSDictionary *)newEntity +Parameters +Parameter Description +newEntity NSDictionary object that contains the entity properties +Example Request/Response +Show Code +Request: +-(NSString*)newEntity { + + //create an entity object + NSMutableDictionary *entity = [[NSMutableDictionary alloc] init ]; + + //Set entity properties + [entity setObject:@"item" forKey:@"type"]; //Required. New entity type to create + [entity setObject:@"milk" forKey:@"name"]; + [entity setObject:@"3.25" forKey:@"price"]; + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate]; + + //call createEntity to initiate the API call + ApigeeClientResponse *response = [appDelegate.dataClient createEntity:entity]; + + @try { + //success + } + @catch (NSException * e) { + //fail + } + +} + +Response: + { + "action" : "post", + "application" : "4a1edb70-d7a8-11e2-9ce3-f315e5aa568a", + "params" : { }, + "path" : "/items", "uri" : "http://api.usergrid.com/my-org/my-app/items", + "entities" : [ { + "uuid" : "83e9b7ea-e8f5-11e2-84df-e94123890c7a", + "type" : "item", + "name" : "milk", + "created" : 1373415195230, + "modified" : 1373415195230, + "metadata" : { + + "path" : "/items/83e9b7ea-e8f5-11e2-84df-e94123890c7a" + }, + "name" : "milk", + "price" : "3.25" + } ], + "timestamp" : 1373415195225, + "duration" : 635, + "organization" : "my-org", + "applicationName" : "my-app" + } + + +### 6. Creating multiple custom entities + +Request Syntax +curl -X POST https://api.usergrid.com//// -d '[{}, {}, ...]' +Parameters +Parameter Description +org Organization UUID or name +app Application UUID or name +entity_type Custom entity type to create. API Services will create a corresponding collection if one does not already exist. To add an entity to an existing collections, use the collection name or colleciton UUID in place of the entity type. +entity Comma-separated list of entity objects to create. Each object should be formatted as a comma-separated list of entity properties, formatted as key-value pairs in the format : +Example Request/Response +Show Code +Request: +curl -X POST "https://api.usergrid.com/your-org/your-app/item" -d '[{"name":"milk", "price":"3.25"}, {"name":"bread", "price":"2.50"}]' +Response: +{ + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e9sjwsf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "f3a8061a-ef0b-11e2-9e92-5f4a65c16193", + "type" : "item", + "name" : "milk", + "price" : "3.25", + "created" : 1374084538609, + "modified" : 1374084538609, + "metadata" : { + "path" : "/multis/f3a8061a-ef0b-11e2-9e92-5f4a65c16193" + }, + "name" : "milk" + }, { + "uuid" : "f3be262a-ef0b-11e2-a51b-6715d5ef47a6", + "type" : "item", + "name" : "bread", + "price" : "2.50", + "created" : 1374084538754, + "modified" : 1374084538754, + "metadata" : { + "path" : "/items/f3be262a-ef0b-11e2-a51b-6715d5ef47a6" + }, + "name" : "bread" + } ], + "timestamp" : 1374084538584, + "duration" : 388, + "organization" : "your-org", + "applicationName" : "your-app" +} + +### 7. Creating an entity with sub-properties + +SDK Method +(ApigeeClientResponse *)createEntity:(NSDictionary *)newEntity +Parameters +Parameter Description +newEntity NSMutableDictionary object that contains the entity properties +Example Request/Response +Show Code +Request: +-(NSString*)newEntity { + + //Initialize an object for the new entity to be created + NSMutableDictionary *entity = [ [NSMutableDictionary alloc] init ]; + + //Initialize an object for each nested variety object + NSMutableDictionary *variety_1 = [ [NSMutableDictionary alloc] init ]; + NSMutableDictionary *variety_2 = [ [NSMutableDictionary alloc] init ]; + NSMutableDictionary *variety_3 = [ [NSMutableDictionary alloc] init ]; + + //Initialize an array to hold the nested variety objects + NSMutableArray *variety_list = [ [NSMutableArray alloc] init]; + + [variety_1 setObject:@"1%" forKey:@"name"]; + [variety_1 setObject:@"3.25" forKey:@"price"]; + [variety_1 setObject:@"0393847575533445" forKey:@"sku"]; + + [variety_2 setObject:@"whole" forKey:@"name"]; + [variety_2 setObject:@"3.85" forKey:@"price"]; + [variety_2 setObject:@"0393394956788445" forKey:@"sku"]; + + [variety_3 setObject:@"skim" forKey:@"name"]; + [variety_3 setObject:@"4.00" forKey:@"price"]; + [variety_3 setObject:@"0390299933488445" forKey:@"sku"]; + + //Add the variety objects to the array + [variety_list addObject:variety_1]; + [variety_list addObject:variety_2]; + [variety_list addObject:variety_3]; + + //Set the item entity properties + [entity setObject:@"item" forKey:@"type"]; //Required. New entity type to create + [entity setObject:@"milk" forKey:@"name"]; + + //Set the variety_list array as the value of the 'varieties' property + [entity setObject:variety_list forKey:@"varieties"]; + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate]; + + //call createEntity to initiate the API call + ApigeeClientResponse *response = [appDelegate.dataClient createEntity:entity]; + + @try { + //success + } + @catch (NSException * e) { + //fail + } + +} + +Response: +{ + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "0d7cf92a-effb-11e2-917d-c5e707256e71", + "type" : "item", + "name" : "milk", + "created" : 1374187231666, + "modified" : 1374187231666, + "metadata" : { + "path" : "/items/0d7cf92a-effb-11e2-917d-c5e707256e71" + }, + "name" : "milk", + "varieties" : [ { + "name" : "1%", + "price" : "3.25", + "SKU" : "0393847575533445" + }, { + "name" : "whole", + "price" : "3.85", + "SKU" : "0393394956788445" + }, { + "name" : "skim", + "price" : "4.00", + "SKU" : "0390299933488445" + } ] + } ], + "timestamp" : 1374187450826, + "duration" : 50, + "organization" : "your-org", + "applicationName" : "your-app" +} + + +### 8. Retrieving an entity + +SDK Method + + (ApigeeClientResponse *)getEntities: (NSString *)endpoint query:(NSString *)query + +Properties + +Parameter Description +--------- ----------- +endpoint The collection and entity identifier of the entity to be retrieved. +query An optional query string. Requests for a specific entity should set the value to nil + +Endpoint exported in the following format: / + +Example Request/Response + +Request: + + -(NSString*)getEntity { + + //specify the entity collection and UUID or name to be retrieved + NSString *endpoint = @"items/b3aad0a4-f322-11e2-a9c1-999e12039f87"; + + NSString *query = nil; + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; + + //call getEntities to initiate the API call + ApigeeClientResponse *response = [appDelegate.dataClient getEntities:endpoint queryString:query]; + + @try { + //success + } + + @catch (NSException * e) { + //fail + } + + } + +Response: + + { + "action" : "get", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/amuramoto/sandbox/items", + "entities" : [ { + "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "type" : "item", + "name" : "milk", + "created" : 1378405020796, + "modified" : 1378405020796, + "metadata" : { + "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4" + }, + "name" : "milk", + "price" : "3.25" + } ], + "timestamp" : 1378405025763, + "duration" : 31, + "organization" : "amuramoto", + "applicationName" : "sandbox" + } + +### 9. Retrieving multiple entities + +SDK Method + + (ApigeeClientResponse *)getEntities: (NSString *)type queryString:(NSString *)queryString + +Properties + +Parameter Description +--------- ----------- +type The entity type being retrieved +queryString A query string of entity properties to be matched for the entities to be retrieved. + +Query string is expected in the following format: = OR = OR ... + +Example Request/Response + +Request: + + -(NSString*)getEntity { + + //specify the entity type to be retrieved + NSString *type = @"item"; + + //specify the uuid of the entity to be retrieved in a query string + NSString *query = @"uuid = b3aad0a4-f322-11e2-a9c1-999e12039f87 or name = 'bread'"; + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; + + //call createEntity to initiate the API call + ApigeeClientResponse *response = [appDelegate.dataClient getEntities:type queryString:query]; + + @try { + //success + } + @catch (NSException * e) { + //fail + } + + } + +Response: + + { + "action" : "get", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { + "ql" : [ "name='milk' OR UUID=1a9356ba-1682-11e3-a72a-81581bbaf055" ] + }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "type" : "item", + "name" : "milk", + "created" : 1378405020796, + "modified" : 1378405020796, + "metadata" : { + "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4" + }, + "name" : "milk", + "price" : "3.25" + }, { + "uuid" : "1a9356ba-1682-11e3-a72a-81581bbaf055", + "type" : "item", + "name" : "bread", + "created" : 1378423379867, + "modified" : 1378423379867, + "metadata" : { + "path" : "/items/1a9356ba-1682-11e3-a72a-81581bbaf055" + }, + "name" : "bread", + "price" : "2.50" + } ], + "timestamp" : 1378423793729, + "duration" : 63, + "organization" : "your-org", + "applicationName" : "your-app", + "count" : 2 + } + + +### 10. Updating an entity + +SDK Method + + (ApigeeClientResponse *)updateEntity: (NSString *)entityID entity:(NSDictionary *)updatedEntity + +Parameters + +Parameter Description +--------- ----------- +entityID UUID of the entity to be updated +updatedEntity NSMutableDictionary containing the properties to be updated + +Example Request/Response + +Request: + + -(NSString*)updateEntity { + + //UUID of the entity to be updated + NSString *entityID = @"f42752aa-08fe-11e3-8268-5bd5fa5f701f"; + + //Create an entity object + NSMutableDictionary *updatedEntity = [ [NSMutableDictionary alloc] init ]; + + //Set entity properties to be updated + [updatedEntity setObject:@"item" forKey:@"type"]; //Required - entity type + [updatedEntity setObject:@"in-stock" forKey:@"availability"]; + [updatedEntity setObject:@"4.00" forKey:@"price"]; + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate]; + + //call updateEntity to initiate the API call + ApigeeClientResponse *response = [appDelegate.dataClient updateEntity:entityID entity:updatedEntity]; + + @try { + + //success + + } + @catch (NSException * e) { + //fail + } + + } + +Response: + + { + "action" : "put", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "type" : "item", + "name" : "milk", + "created" : 1378405020796, + "modified" : 1378505705077, + "availability" : "in-stock", + "metadata" : { + "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4" + }, + "name" : "milk", + "price" : "4.00" + } ], + "timestamp" : 1378505705050, + "duration" : 87, + "organization" : "your-org", + "applicationName" : "your-app" + } + + +### 11. Updating a sub-property + +SDK Method + + (ApigeeClientResponse *)updateEntity: (NSString *)entityID entity:(NSDictionary *)updatedEntity + +Parameters + +Parameter Description +--------- ----------- +entityID UUID of the entity to be updated +updatedEntity Entity object containing the properties to be updated + +Example Request/Response + +Request: + + -(NSString*)updateEntity { + + //UUID of the entity to be updated + NSString *entityID = @"f42752aa-08fe-11e3-8268-5bd5fa5f701f"; + + //Define our two sub-properties to include in the update + NSMutableDictionary *subproperty1 = [ [NSMutableDictionary alloc] init]; + NSMutableDictionary *subproperty2 = [ [NSMutableDictionary alloc] init]; + [subproperty1 setObject:@"1%" forKey:@"name"]; + [subproperty1 setObject:@"3.25" forKey:@"price"]; + [subproperty2 setObject:@"whole" forKey:@"name"]; + [subproperty2 setObject:@"4.00" forKey:@"price"]; + + //Put our sub-properties into an NSArray + NSArray *subproperties = [ [NSArray alloc] initWithObjects:props1,props2, nil]; + + //Create an NSMutableDictionary to hold our updates + NSMutableDictionary *updatedEntity = [ [NSMutableDictionary alloc] init ]; + + //Set the properties to be updated + [updatedEntity setObject:@"item" forKey:@"type"]; //Required - entity type + [updatedEntity setObject:props forKey:@"varieties"]; + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate]; + + //call createEntity to initiate the API call + ApigeeClientResponse *response = [appDelegate.dataClient updateEntity:entityID entity:updatedEntity]; + + @try { + + //success + + } + @catch (NSException * e) { + //fail + } + + } + +Response: + + { + "action" : "put", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "type" : "item", + "name" : "milk", + "created" : 1378405020796, + "modified" : 1378761459069, + "availability" : "in-stock", + "metadata" : { + "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4" + }, + "name" : "milk", + "uri" : "http://api.usergrid.com/your-org/your-app/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4", + "varieties" : [ { + "name" : "1%", + "price" : "3.25" + }, { + "name" : "whole", + "price" : "4.00" + } ] + } ], + "timestamp" : 1378761459047, + "duration" : 62, + "organization" : "your-org", + "applicationName" : "your-app" + } + + +### 12. Deleting data entities + +SDK Method + + (ApigeeClientResponse *)removeEntity: (NSString *)type entityID:(NSString *)entityID + +Properties + +Parameter Description +--------- ----------- +type The entity type being deleted +entityID The UUID or name of the entity to be removed + +Example Request/Response + +Request: + + -(NSString*)deleteEntity { + + //specify the entity type to be deleted + NSString *type = @"item"; + + //specify the uuid or name of the entity to be deleted + NSString *entityId = @"milk"; + + //we recommend you call ApigeeClient from your AppDelegate. + //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios + //create an instance of AppDelegate + AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; + + //call removeEntity to initiate the API call + ApigeeClientResponse *response = [appDelegate.dataClient removeEntity:type entityID:entityId]; + + @try { + //success + } + @catch (NSException * e) { + //fail + } + } + +Response: + + { + "action" : "delete", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/items", + "uri" : "http://api.usergrid.com/your-org/your-app/items", + "entities" : [ { + "uuid" : "328fe64a-19a0-11e3-8a2a-ebc6f49d1fc4", + "type" : "item", + "name" : "milk", + "created" : 1378766158500, + "modified" : 1378766158500, + "metadata" : { + "path" : "/items/328fe64a-19a0-11e3-8a2a-ebc6f49d1fc4" + }, + "name" : "milk", + "price" : "3.25" + } ], + "timestamp" : 1378766172016, + "duration" : 324, + "organization" : "your-org", + "applicationName" : "your-app" + } + + +## Data Queries + +### 13. Querying your data + +## Entity Connections + +### 14. Connecting users other data +### 15. Retrieving user connection data +### 16. Disconnecting entities + +## Permissions & Roles + +### 17. Assigning permissions +### 18. Removing permissions +### 19. Assigning permissions +### 20. Removing permissions +### 21. Creating roles +### 22. Assigning roles +### 23. Removing roles + +## Authentication + +### 24. Application user authentication (user login) +### 25. Application client authentication +### 26. Admin user authentication +### 27. Organization client authentication +### 28. Revoking tokens (user logout) + +# Working with Users & Groups + +### 29. Creating users +### 30. Retrieving user data +### 31. Setting or updating password +### 32. Creating groups +### 33. Retrieving group data +### 34. Retrieving a group's users +### 35. Adding users groups +### 36. Deleting user group + +## Activities & Feeds + +### 37. Posting a user activity +### 38. Posting an activity to a group +### 39. Creating an activity for a user's followers in a group +### 40. Retrieving a user's activity feed +### 41. Retrieving a group's activity feed + +## Events & Counters + +### 42. Creating & incrementing counters +### 43. Retrieving counters +### 44. Retrieving counters by time interval + +## Managing Orgs & Apps + +### 46. Creating an organization +### 47. Getting an organization +### 48. Activating an organization +### 49. Reactivating an organization +### 50. Generating organization client credentials +### 51. Retrieving organization client credentials +### 52. Getting an organization's activity feed +### 53. Getting the applications in an organization +### 54. Getting the admin users in an organization +### 55. Removing an admin user from an organization +### 56. Creating an organization application +### 57. Generating application credentials +### 58. Getting application credentials + +## Managing Admin Users + +### 59. Creating an admin user +### 60. Updating an admin user +### 61. Getting an admin user +### 62. Setting an admin user's password +### 63. Resetting an admin user's password +### 64. Activating an admin user +### 65. Reactivating an admin user +### 66. Getting an admin user's activity feed + + \ No newline at end of file diff --git a/content/docs/_sources/sdks/ios.txt b/content/docs/_sources/sdks/ios.txt new file mode 100644 index 0000000000..328b09a8d0 --- /dev/null +++ b/content/docs/_sources/sdks/ios.txt @@ -0,0 +1 @@ +# iOS SDK \ No newline at end of file diff --git a/content/docs/_sources/sdks/java.txt b/content/docs/_sources/sdks/java.txt new file mode 100644 index 0000000000..a2a50860cf --- /dev/null +++ b/content/docs/_sources/sdks/java.txt @@ -0,0 +1 @@ +# Java SDK \ No newline at end of file diff --git a/content/docs/_sources/sdks/javascript.txt b/content/docs/_sources/sdks/javascript.txt new file mode 100644 index 0000000000..685d42dd6a --- /dev/null +++ b/content/docs/_sources/sdks/javascript.txt @@ -0,0 +1,3 @@ +# JavaScript/HTML5 SDK + + diff --git a/content/docs/_sources/sdks/sdk-outline.txt b/content/docs/_sources/sdks/sdk-outline.txt new file mode 100644 index 0000000000..48bd3fc7c5 --- /dev/null +++ b/content/docs/_sources/sdks/sdk-outline.txt @@ -0,0 +1,111 @@ +# Usergrid SDK Documentation outline + +## Getting Started + +### Installing the SDK +### Building from Source + +# Usergrid SDK Reference with Examples + +The 66 topics listed below are each documented in the Usergrid documentation and +for each the docs provide an API reference and example for each of these clients: +curl, iOS, Android, JavaScript, Ruby and Node.js. + +## Working with Collections + +### 1. Creating collections +### 2. Retrieving collections +### 3. Updating collections +### 4. Deleting collections + +## Working with Entities + +### 5. Creating a custom entity +### 6. Creating multiple custom entities +### 7. Creating an entity with sub-properties +### 8. Retrieving an entity +### 9. Retrieving multiple entities +### 10. Updating an entity +### 11. Updating a sub-property +### 12. Deleting data entities + +## Data Queries + +### 13. Querying your data + +## Entity Connections + +### 14. Connecting users other data +### 15. Retrieving user connection data +### 16. Disconnecting entities + +## Permissions & Roles + +### 17. Assigning permissions +### 18. Removing permissions +### 19. Assigning permissions +### 20. Removing permissions +### 21. Creating roles +### 22. Assigning roles +### 23. Removing roles + +## Authentication + +### 24. Application user authentication (user login) +### 25. Application client authentication +### 26. Admin user authentication +### 27. Organization client authentication +### 28. Revoking tokens (user logout) + +# Working with Users & Groups + +### 29. Creating users +### 30. Retrieving user data +### 31. Setting or updating password +### 32. Creating groups +### 33. Retrieving group data +### 34. Retrieving a group's users +### 35. Adding users groups +### 36. Deleting user group + +## Activities & Feeds + +### 37. Posting a user activity +### 38. Posting an activity to a group +### 39. Creating an activity for a user's followers in a group +### 40. Retrieving a user's activity feed +### 41. Retrieving a group's activity feed + +## Events & Counters + +### 42. Creating & incrementing counters +### 43. Retrieving counters +### 44. Retrieving counters by time interval + +## Managing Orgs & Apps + +### 46. Creating an organization +### 47. Getting an organization +### 48. Activating an organization +### 49. Reactivating an organization +### 50. Generating organization client credentials +### 51. Retrieving organization client credentials +### 52. Getting an organization's activity feed +### 53. Getting the applications in an organization +### 54. Getting the admin users in an organization +### 55. Removing an admin user from an organization +### 56. Creating an organization application +### 57. Generating application credentials +### 58. Getting application credentials + +## Managing Admin Users + +### 59. Creating an admin user +### 60. Updating an admin user +### 61. Getting an admin user +### 62. Setting an admin user's password +### 63. Resetting an admin user's password +### 64. Activating an admin user +### 65. Reactivating an admin user +### 66. Getting an admin user's activity feed + \ No newline at end of file diff --git a/content/docs/_sources/sdks/tbd.txt b/content/docs/_sources/sdks/tbd.txt new file mode 100644 index 0000000000..279d128a63 --- /dev/null +++ b/content/docs/_sources/sdks/tbd.txt @@ -0,0 +1 @@ +# COMING SOON... \ No newline at end of file diff --git a/content/docs/_sources/security-and-auth/app-security.txt b/content/docs/_sources/security-and-auth/app-security.txt new file mode 100644 index 0000000000..9dcf3e21bc --- /dev/null +++ b/content/docs/_sources/security-and-auth/app-security.txt @@ -0,0 +1,19 @@ +# Security & token authentication + +Any app you put into production should feature security that protects your app, your users, and your app's data. Implementing security means taking steps in your mobile app's code and in your API Services BaaS application. + +__Important__: When you register for the API Services BaaS, you get a sandbox application that you can use to try things out. This application is not for use in production. By default, the sandbox application is not protected by any security measures whatsoever. Use the sandbox only for experimentation, and only with data that isn't in any way sensitive. + +When securing your app, follow these high-level steps: + +1. Define the rules that will govern access by your app's users to your app's data and features. You do this with the admin portal by creating permission rules, then associating those rules with your users. For more information, see [Using Permissions](managing-access-defining-permission-rules.html). +2. Write code through which your app's users can verify who they are to your application. You do this by writing code that uses their username and password as credentials to initially authenticate with your application, then uses a token thereafter. (This authentication style supports the OAuth 2.0 model.) For more information, see [Authenticating users & app clients](autheticating-users-and-application-clients.html). +3. Be sure to use coding best practices that help ensure that your app is protected from malicious attacks. For more information, see [Security best practices](security-best-practices.html). + +The following illustration describes these high-level areas. + +.. image:: securitymodel0.png + + + + diff --git a/content/docs/_sources/security-and-auth/authenticating-api-requests.txt b/content/docs/_sources/security-and-auth/authenticating-api-requests.txt new file mode 100644 index 0000000000..d29e4cbbfd --- /dev/null +++ b/content/docs/_sources/security-and-auth/authenticating-api-requests.txt @@ -0,0 +1,38 @@ +# Authenticating API requests + +With the exception of the 'sandbox' application that is created with every Usergrid organization, all applications are secured by default. This means that to access your data store, a valid access token must be sent with all API requests to authenticate that the requester is authorized to make API calls to the resources they are attempting the access. + +This article describes how to use access tokens to access the Usergrid API, and how to manage access tokens, including revoking and changing token time to live. + +For information on generating access tokens/authenticating users and clients, see [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html). + +## Authenticating with access tokens +When you obtain an access token, you must provide it with every subsequent API call that you make. There are two ways to provide your access token. + +You can add the token to the API query string: + + https:///{org-name}/{app-name}/users?access_token={access_token} + +You can include the token in an HTTP authorization header: + + Authorization: Bearer {access_token} + +

Note


 +Note: The Usergrid documentation assumes you are providing a valid access token with every API call whether or not it is shown explicitly in the examples. Unless the documentation specifically says that you can access an API endpoint without an access token, you should assume that you must provide it. One application that does not require an access token is the sandbox application. The Guest role has been given full permissions (/** for GET, POST, PUT, and DELETE) for this application. This eliminates the need for a token when making application level calls to the sandbox app. For further information on specifying permissions, see [Using Permissions](security-and-auth/using-permissions.html). +

+ +## Authenticating with client ID and client secret + +Another option for authenticating your API requests is using either your organization client ID and client secret, or your application client ID and client secret, which will authenticate your request as an organization or application admin, respectively. Organization credentials can be found in the 'Org Overview' section of the admin portal, and application credentials can be found in the 'Getting Started' section of the admin portal. + +

WARNING


 +Warning: For server-side use only +You should never authenticate this way from a client-side app such as a mobile app. A hacker could analyze your app and extract the credentials for malicious use even if those credentials are compiled and in binary format. See [Security Best Practices](../security-and-auth/securing-your-app.html) for additional considerations in keeping access to your app and its data secure. +

+ +This can be a convenient way to authenticate API requests, since there is no need to generate and manage an access token, but please note that you should be very cautious when implementing this type of authentication. Organization-level authentication grants full permission to perform any supported call against your organization and every application in it, and application-level authentication grants full permission to perform any supported call against all of the resources in an application. Should your client id and client secret be compromised, a malicious user would gain broad access to your organization or application. + +To authenticate using client id and secret, append the following parameters to your request URL: + + client_id=&client_secret= + \ No newline at end of file diff --git a/content/docs/_sources/security-and-auth/authenticating-users-and-application-clients.txt b/content/docs/_sources/security-and-auth/authenticating-users-and-application-clients.txt new file mode 100644 index 0000000000..e1ada4858b --- /dev/null +++ b/content/docs/_sources/security-and-auth/authenticating-users-and-application-clients.txt @@ -0,0 +1,128 @@ +# Authenticating users & app clients + +To protect your Usergrid application data, one of the steps you'll take is to authenticate your app's users. By ensuring that they are who they say they are, you can help ensure that your application's data is available in secure ways. After you've created permission rules that define access to your application and have associated these rules with users, you'll want to add code that authenticates your user, as described in this topic. + +

Note


 +You manage access to your application's data by creating permission rules that govern which users can do what. Users authenticated as Application User have access according to these rules. For more about managing permissions, see [Using Permissions](using-permissions.html). +

+ + +## Authentication levels +Usergrid supports four levels of authentication: + +* __Application user__: Grant's user access to an API Services application, based on the roles and permissions assigned to the user. +* __Application client__: Grants full access to perform API requests against an API Services application. +* __Organization client__: Grants full access to perform API requests against an API Services organization. +* __Admin user__: Grants full access to perform API requests against any API Services organization that the user is an admin of. + +Because the scope of access provided by the application client, organization client, and admin user authentication levels is so broad (and as a result, so powerful), it's a bad practice to use them from a mobile app or any client-side code. Instead, they're better suited to server-side implementations, such as web applications. + +For a more detailed description of available authentication levels, see [Authentication levels](user-authentication-types.html). + +## Application user authentication (user login) +Using the username and password values specified when the user entity was created, your app can connect to the Usergrid application endpoint to request an access token. It's also acceptable to use the user's email address in place of the username. + +### Using the SDKs +When a user is logged in using the Usergrid iOS, JavaScript, node.JS and Android SDKs, the returned token is automatically stored in the UsergridDataClient (iOS), DataClient (Android), or Usergrid.Client (JavaScript/node.JS) class instance, and will be sent to the API with all subsequent method calls. + +#### Request syntax + + curl -X POST "https://api.usergrid.com///token" -d '{"grant_type":"password", "username":, "password":}' + +#### Example request + + curl -X POST "https://api.usergrid.com/my-org/my-app/token" -d '{"grant_type":"password", "username":"john.doe", "password":"testpw"}' + +#### Example response + +The results include the access token needed to make subsequent API requests on behalf of the application user: + + { + "access_token": "5wuGd-lcEeCUBwBQVsAACA:F8zeMOlcEeCUBwBQVsAACA:YXU6AAABMq0hdy4", + "expires_in": 3600, + "user": { + ... + } + } + +## Application client authentication +Using your app’s client id and client secret values, your app can connect to the Usergrid application endpoint to request an access token. The client ID and secret for your app can be found in 'Getting Started' section of the API Services admin portal, under 'Server App Credentials'. + +

WARNING


 +Warning: You should never authenticate this way from a client-side app such as a mobile app. A hacker could analyze your app and extract the credentials for malicious use even if those credentials are compiled and in binary format. See [Security Best Practices](../security-and-auth/securing-your-app.html) for additional considerations in keeping access to your app and its data secure. +

+ +### Request syntax + + curl -X POST "https://api.usergrid.com///token" -d '{"grant_type":"client_credentials", "client_id":, "client_secret":""}' + +### Example request + + curl -X POST "https://api.usergrid.com/my-org/my-app/token" -d '{"grant_type":"client_credentials", "client_id":"YXB7NAD7EM0MEeJ989xIxPRxEkQ", "client_secret":"YXB7NAUtV9krhhMr8YCw0QbOZH2pxEf"}' + +### Example response + +The results include the access token needed to make subsequent API requests on behalf of the application: + + { + "access_token": "F8zeMOlcEeCUBwBQVsAACA:YXA6AAABMq0d4Mep_UgbZA0-sOJRe5yWlkq7JrDCkA", + "expires_in": 3600, + "application": { + ... + } + } + +## Admin user authentication +If you do require admin user access, your app can connect to the Usergrid management endpoint to request an access token. Your app supplies the username and password of an admin user in the request. + +

WARNING


 +Warning: Authenticating as an admin user grants full access to one or more organizations and all of the applications contained in those organizations. Due to this, be cautious when implementing this type of authentication in client-side code. Instead, consider implementing admin user access in server-side code only. See [Security Best Practices](../security-and-auth/securing-your-app.html) for additional considerations in keeping access to your app and its data secure. +

+ +### Request syntax + + curl -X POST "https://api.usergrid.com/management/token" -d '{"grant_type":"password", "username":, "password":}' + +### Example Request + + curl -X POST "https://api.usergrid.com/management/token" -d '{"grant_type":"password", "username":"testadmin", "password":"testadminpw"}' + +### Example response + +The results include the access token needed to make subsequent API requests on behalf of the admin user: + + { + "access_token": "f_GUbelXEeCfRgBQVsAACA:YWQ6AAABMqz_xUyYeErOkKjnzN7YQXXlpgmL69fvaA", + "expires_in": 3600, + "user": { + ... + } + } + +## Organization client authentication +If you do require organization level access, your app can connect to the Usergrid management endpoint to request an access token. Access to an organization requires the client id and client secret credentials. The client ID and secret for your organization can be found on the 'Org Administration' page of the API Services admin console under 'Organization API Credentials'. + +

WARNING


 +Warning: You should never authenticate this way from a client-side app such as a mobile app. A hacker could analyze your app and extract the credentials for malicious use even if those credentials are compiled and in binary format. See [Security Best Practices](../security-and-auth/securing-your-app.html) for additional considerations in keeping access to your app and its data secure. +

+ +### Request syntax + + curl -X POST "https://api.usergrid.com/management/token" -d '{"grant_type":"client_credentials", "client_id":, "client_secret":}' + +### Example request + + curl -X POST "https://api.usergrid.com/management/token" -d '{"grant_type":"client_credentials", "client_id":"YXB7NAD7EM0MEeJ989xIxPRxEkQ", "client_secret":"YXB7NAUtV9krhhMr8YCw0QbOZH2pxEf"}' + +### Example response + +The results include the access token needed to make subsequent API requests to the organization: + + { + "access_token": "gAuFEOlXEeCfRgBQVsAACA:b3U6AAABMqz-Cn0wtDxxkxmQLgZvTMubcP20FulCZQ", + "expires_in": 3600, + "organization": { + ... + } + } + \ No newline at end of file diff --git a/content/docs/_sources/security-and-auth/changing-token-time-live-ttl.txt b/content/docs/_sources/security-and-auth/changing-token-time-live-ttl.txt new file mode 100644 index 0000000000..2148d36dd2 --- /dev/null +++ b/content/docs/_sources/security-and-auth/changing-token-time-live-ttl.txt @@ -0,0 +1,61 @@ +# Changing token expiration (time-to-live) + +An access token has a “time-to-live” (ttl), which is the maximum time that the access token will be valid for use within the application. With the Usergrid, you can change the default ttl for all application user tokens, set the ttl for an individual token at the time of creation, or revoke one or more tokens. This gives you a high degree of control over access to your Usergrid account and data store. + +## Default ttl +By default, all tokens have a system-defined time-to-live of 7 days (604800 seconds). Note that Token ttl is specified in milliseconds, but when a token is created, the API response will return the ttl in seconds. + +## Changing the default ttl +You can change the default ttl for all application user tokens (that is, tokens associated with a user entity) by updating the application entity’s accesstokenttl property. Changing the default ttl will only affect new tokens. Any existing tokens will not be affected. + +Please note that this does not apply to application client, organization client or admin user tokens. For more on obtaining tokens for these other authorization levels, see [Authenticating users and application clients](authenticating-users-and-application-clients.html). + +__Note__: If you set ttl=0, the token will never expire. This can pose a security risk and should be used with caution. + +### Request syntax + + curl -X PUT https://api.usergrid.com// -d '{"accesstokenttl":}' + +### Example Request + + curl -X PUT https://api.usergrid.com/your-org/your-app -d '{"accesstokenttl":"1800000"}' + +### Example response + + { + "action" : "put", + "application" : "d878de4r-99a7-11e3-b31d-5373d7165c2d", + "params" : { + "access_token" : [ "DFR4d5M1mJmoEeOGVPncm-g9qgAAAURv_lfQ7uu6aYHjJJn7QCrGoVnvU-ob5Ko" ] + }, + "uri" : "https://api.usergrid.com/amuramoto/secured", + "entities" : [ { + "uuid" : "d878de4r-99a7-11e3-b31d-5373d7165c2d", + "type" : "application", + "name" : "your-org/your-app", + "created" : 1392843003032, + "modified" : 1392843615777, + "accesstokenttl" : 1800000, + "organizationName" : "your-org", + "applicationName" : "your-app", + "apigeeMobileConfig" : "{...}", + "metadata" : { + "collections" : [ "activities", "assets", "devices", "events", "folders", "groups", "roles", "users" ] + } + } ], + "timestamp" : 1392843615767, + "duration" : 28, + "organization" : "your-org", + "applicationName" : "your-app" + } + +## Changing ttl when a token is created +When you request an access token, you can override its ttl by including a ttl property in the body of the request when the token is created. This applies to tokens for all authentication levels, including application user, admin user, organization client, and application client authentication levels. + +The ttl must be equal to or less than the value of the application entity's accesstokenttl property. If you specify a ttl value greater than the value of accesstokenttl, an error message is returned that indicates the maximum time to live value that can be specified. + +For example, the following would create an application user token with a ttl of 180000000 milliseconds: + + curl -X POST https://api.usergrid.com/your-org/your-app/token -d '{"username":"someUser", "password":"somePassword", "grant_type":"password", "ttl":"180000000"}' + +__Note__: If you set ttl=0, the token will never expire. This can pose a security risk and should be used with caution. \ No newline at end of file diff --git a/content/docs/_sources/security-and-auth/facebook-sign.txt b/content/docs/_sources/security-and-auth/facebook-sign.txt new file mode 100644 index 0000000000..970cb33c04 --- /dev/null +++ b/content/docs/_sources/security-and-auth/facebook-sign.txt @@ -0,0 +1,158 @@ +# Facebook sign in + +You can authenticate your Usergrid requests by logging into Facebook. To access Usergrid resources, you need to provide an access token with each request (unless you use the sandbox app). You can get an access token by connecting to an appropriate web service endpoint and providing the correct client credentials — this is further described in Authenticating users and application clients. However, you can also obtain an access token by logging into Facebook. + +To enable authentication to Usergrid through Facebook, do the following in your app: + +1. Make a login call to the Facebook API (do this using the Facebook SDK or API). If the login succeeds, a Facebook access token is returned. +2. Send the Facebook access token to Usergrid. If the Facebook access token is valid and the user does not already exist in Usergrid, Usergrid provisions a new Usergrid user. It also returns an Usergrid access token, which you can use for subsequent Usergrid API calls. Behind the scenes, Usergrid uses the Facebook access token to retrieve the user's profile information from Facebook. +3. If the Facebook access token is invalid, Facebook returns an OAuth authentication error, and the login does not succeed. + +The request to authenticate to Usergrid using a Facebook access token is: + + GET https://api.usergrid.com/{my_org}/{my_app}/auth/facebook?fb_access_token={fb_access_token} + +where: + +* ``{my_org}`` is the organization UUID or organization name. +* ``{my_app}`` is the application UUID or application name. +* ``{fb_access_token}`` is the Facebook access token. + +## Facebook login example +The Facebook technical guides for login present detailed information on how to add Facebook login to your app. Instructions are provided for JavaScript, iOS, and Android. + +In brief, here are the steps for JavaScript. You can see these steps implemented in the Facebook login example packaged with the JavaScript SDK for Usergrid (which you can download in ZIP format or tar.gz format). The Facebook login example is in the ``/examples/facebook`` directory of the extracted download. The code example snippets shown below are taken from the Facebook login example. + +### Step 1: Create a Facebook app +Create a new app on the Facebook App Dashboard. Enter your app's basic information. Once created, note the app ID shown at the top of the dashboard page. + +### Step 2: Invoke the Facebook OAuth dialog +Invoke the Facebook OAuth Dialog. To do that, redirect the user's browser to a URL by inserting the following Javascript code after the opening tag in your app’s HTML file: + + https://www.facebook.com/dialog/oauth/? + client_id={YOUR_APP_ID} + &redirect_uri={YOUR_REDIRECT_URL} + &state={YOUR_STATE_VALUE} + &scope={COMMA_SEPARATED_LIST_OF_PERMISSION_NAMES} + &response_type={YOUR_RESPONSE_TYPE} + +where: + +``{YOUR_APP_ID}`` is the app ID. +``{YOUR_REDIRECT_URL}`` is the application UUID or application name. +``{YOUR_STATE_VALUE}`` is a unique string used to maintain application state between the request and callback. +``{COMMA_SEPARATED_LIST_OF_PERMISSION_NAMES}`` is a comma separated list of permission names which you would like the user to grant your application. +``{YOUR_RESPONSE_TYPE}``is the requested response type, either code or token. Defaults to code. Set the response type to token. With the response type set to token, the Dialog's response will include an OAuth user access token in the fragment of the URL the user is redirected to, as per the client-side authentication flow. + +Here is how it’s done in the Facebook login example: + + var apiKey = $("#api-key").val(); + var location = window.location.protocol + '//' + window.location.host; + var path = window.location.pathname; + + var link = "https://www.facebook.com/dialog/oauth?client_id="; + link += apiKey; + link += "&redirect_uri="; + link += location+path + link += "&scope&COMMA_SEPARATED_LIST_OF_PERMISSION_NAMES&response_type=token"; + + //now forward the user to facebook + window.location = link; + +Notice that the response type is set to token. As a result, a Facebook access token will be appended to the URL to which the user is redirected. + +### Step 3: Add the JavaScript SDK for Facebook +Add the following Javascript SDK initialization code after the code that invokes the Facebook OAuth Dialog. The code will load and initialize the JavaScript SDK in your HTML page. Replace ``YOUR_APP_ID`` with the App ID noted in Step 1, and WWW.YOUR_DOMAIN.COM with your own domain. + + window.fbAsyncInit = function() { + FB.init({ + appId : 'YOUR_APP_ID', // App ID + channelUrl : '//WWW.YOUR_DOMAIN.COM/channel.html', // Channel File + status : true, // check login status + cookie : true, // enable cookies to allow the server to access the session + xfbml : true // parse XFBML + }); + +Here is how the window.fbAsynchInit() function is implemented in the Facebook login example: + + //load up the facebook api sdk + window.fbAsyncInit = function() { + FB.init({ + appId : '308790195893570', // App ID + channelUrl : '//usergridsdk.dev//examples/channel.html', // Channel File + status : true, // check login status + cookie : true, // enable cookies to allow the server to access the session + xfbml : true // parse XFBML + }); + }; + +### Step 4. Setup FB.login +Whenever a user is either not logged into Facebook or not authorized for an app, it is useful to prompt them with the relevant dialog. The ``FB.login()`` Javascript SDK function automatically displays the correct one to the user. + +To integrate ``FB.login()`` function in your existing code: + + function login() { + FB.login(function(response) { + if (response.authResponse) { + // connected + } else { + // cancelled + } + }); + } + +Here is how ``FB.login()`` is implemented in the Facebook login example: + + function login(facebookAccessToken) { + client.loginFacebook(facebookAccessToken, function(err, response){ + var output = JSON.stringify(response, null, 2); + if (err) { + var html = '
Oops!  There was an error logging you in. \r\n\r\n';
+            html += 'Error: \r\n' + output+'
'; + } else { + var html = '
Hurray!  You have been logged in. \r\n\r\n';
+            html += 'Facebook Token: ' + '\r\n' + facebookAccessToken + '\r\n\r\n';
+            html += 'Facebook Profile data stored in Usergrid: \r\n' + output+'
'; + } + $('#facebook-status').html(html); + }) + } + +The ``client.loginFacebook()`` function is provided by the Usergrid JavaScript SDK. It uses the Facebook auth token to obtain an Usergrid auth token. If the Facebook access token is valid and the user does not already exist in Usergrid, the function creates a user entity for the user. It also uses the Facebook access token to retrieve the user's profile information from Facebook. + +Here is what the ``client.loginFacebook()`` function looks like: + + Usergrid.Client.prototype.loginFacebook = function (facebookToken, callback) { + var self = this; + var options = { + method:'GET', + endpoint:'auth/facebook', + qs:{ + fb_access_token: facebookToken + } + }; + this.request(options, function(err, data) { + var user = {}; + if (err && self.logging) { + console.log('error trying to log user in'); + } else { + user = new Usergrid.Entity('users', data.user); + self.setToken(data.access_token); + } + if (typeof(callback) === 'function') { + callback(err, data, user); + } + }); + } + +Notice that the function also returns an Usergrid access token, which you can use for subsequent Usergrid API calls. + +Remember to create a client for your app, which is the main entry point to the JavaScript SDK for Usergrid. You need to do this before you can use the SDK. Here’s the code to create a client: + + var client = new Usergrid.Client({ + orgName:'yourorgname', + appName:'yourappname', + logging: true, //optional - turn on logging, off by default + buildCurl: true //optional - turn on curl commands, off by default + }); + diff --git a/content/docs/_sources/security-and-auth/revoking-tokens-logout.txt b/content/docs/_sources/security-and-auth/revoking-tokens-logout.txt new file mode 100644 index 0000000000..386f04fe64 --- /dev/null +++ b/content/docs/_sources/security-and-auth/revoking-tokens-logout.txt @@ -0,0 +1,32 @@ +# Revoking tokens (logout) + +Under certain circumstances, you may need to explicitly revoke one or more tokens associated with a user entity, such as when a user logs out of your app. This is accomplished by making a PUT request to the /revoketoken and /revoketokens endpoints. + +## Revoking tokens (user logout) +If a user has been logged in using the Usergrid iOS, Android, JavaScript or node.JS SDKs, the returned token is automatically stored in the UsergridDataClient (iOS), DataClient (Android), Usergrid.Client (JavaScript), Usergrid.Client (node.JS) class instance. Calling the logout method of the SDK will destroy the token on the server, as well as in the client object. + +### Request syntax + +Revoke all tokens associated with a user entity + + curl -X PUT https://api.usergrid.com///users//revoketokens + +Revoke a specific token associated with a user entity + + curl -X PUT https://api.usergrid.com///users//revoketoken?token= + +### Example request + + curl -X PUT https://api.usergrid.com/your-org/your-app/users/someUser/revoketokens + +Example response + + { + "action" : "revoked user token", + "timestamp" : 1382050891455, + "duration" : 24 + } + +### Revoking admin user tokens + +The /revoketoken and /revoketokens endpoints also work for revoking admin user tokens by making a PUT request to /management/users// diff --git a/content/docs/_sources/security-and-auth/securing-your-app.txt b/content/docs/_sources/security-and-auth/securing-your-app.txt new file mode 100644 index 0000000000..6eb043fad6 --- /dev/null +++ b/content/docs/_sources/security-and-auth/securing-your-app.txt @@ -0,0 +1,44 @@ +# Security best practices + +There a number of actions you should take to ensure that your app is secure before you put it into production. The following is not an exhaustive list, but offers some common best practices you should consider following to keep your app secure when using the Usergrid. + +## Never use the 'sandbox' for a production app +By default, every new Usergrid account has an app named “sandbox” that is already created under your new organization. This app is no different than any other app that you might create, except that the Guest role has been given full permissions (that is, /** for GET, POST, PUT, and DELETE). This eliminates the need for a token when making application level calls, and can make it much easier to get your app up and running; however, it also means that any data in the sandbox application is completely unsecured. + +As with any other app, you can secure the sandbox application by updating its roles and permissions. For more on working with permissions and roles, see [Using Permissions](using-permissions.html). + +## Review permissions in your apps +Prior to launching your app into a production environment, it is advisable to review all the roles and permissions you have set up, as well as the groups and users you have assigned those permissions and roles to. During development, you may find that you added various permissions which may or may not still be required once the app is complete. Review all permissions and delete any that are no longer required. + +Prior to taking your app live, you should secure it by removing any unnecesary Guest permissions. (See [Using Permissions](using-permissions.html) for further information about setting permissions.) After you secure your the app, any calls to the API will need to include an OAuth token. Oauth tokens (also called access tokens) are obtained by the API in response to successful authentication calls. Your app saves the token and uses it for all future calls during that session. Learn more about access tokens in Authenticating users and application clients. + +## Edit the 'default' role +When preparing an application for production use, a good first step is to edit permission rules for the Default role. The permissions in this role will be applied to every user who authenticates with a valid access token. + +For example, in the Default role, you will most likely first want to remove the permission rule that grants full access to all authenticated users: + + GET,PUT,POST,DELETE:/users/me/** + +For more on roles, see [Using Permissions](using-permissions.html). + +Review test accounts +If you created any test user or test administrator accounts during development, these should also be reviewed for relevancy and security. Delete any test accounts that are no longer needed. If these accounts are still needed, make sure that passwords have been secured to the standards required by your app. + +## Use https +Make sure that any calls you make to the API are done using the secure https protocol, and not the insecure http protocol. + +If your app is a web app, that is, an app served by a web server, make sure that the app is served using https. + +## Acquire access tokens in a secure way +There are various methods for acquiring an access token (see [Authenticating users and application clients](authenticating-users-and-application-clients.html). One method is to use the application or organization level client secret-client id combination. This method should not be used in client applications (this is, apps that are deployed to a device, and which authenticate and make calls against the API). + +That’s because a hacker could analyze your app (even a compiled, binary distribution of your app), and retrieve the secret-id combination. Armed with this information, an attacker could gain full access to the data in your account. + +Instead, use application user credentials. This means that your app’s users should provide a username and password. Your app would use these to authenticate against the API and retrieve an access token. + +The client secret-client id combination should be used only in secure, server-side applications where there is no possibility of a hacker gaining control of the credentials. + +## Treat mobile clients as untrustworthy +For mobile access, it is recommended that you connect as an application user with configured access control policies. Mobile applications are inherently untrusted because they can be easily examined and even decompiled. + +Any credentials stored in a mobile app should be considered secure only to the Application User level. This means that if you don’t want the user to be able to access or delete data in your Usergrid application, you need to make sure that you don’t enable that capability through roles or permissions. Because most web applications talk to the database using some elevated level of permissions, such as root, it’s generally a good idea for mobile applications to connect with a more restricted set of permissions. For more information on restricting access through permission rules, see [Using Permissions](using-permissions.html). diff --git a/content/docs/_sources/security-and-auth/user-authentication-types.txt b/content/docs/_sources/security-and-auth/user-authentication-types.txt new file mode 100644 index 0000000000..d02e8d399a --- /dev/null +++ b/content/docs/_sources/security-and-auth/user-authentication-types.txt @@ -0,0 +1,63 @@ +# Authentication levels + +Usergrid supports four levels of authentication, but only one of them is used when checking a registered user's permissions. The other three levels are useful for authenticating other application or web clients that require higher-level access to your Usergrid application or organization. Because the scope of access that the other authentication levels provide is so broad (and as a result, so powerful), it's a bad practice to use them from a mobile app. Instead, they're better suited to other client apps, such as web applications. + +## Configuring authentication levels +Access permissions can only be configured for the 'application user' – this can be done both programmatically and in the admin portal. The application, organization and admin clients cannot be configured, and can only be accessed programmatically via the API. + +For more about creating and managing roles and permissions for application users, see [Using Permissions](security-and-auth/using-permissions.html) and [Using Roles](security-and-auth/using-roles.html). For a look at how security features fit together, see [App Security Overview](../security-and-auth/app-security.html). + +## User authentication level + + + + + + + + + + +
Authentication LevelDescription
Application userThis is the standard authentication type you will use to implement user login for your app. The application user level allows access to your Usergrid application as governed by the permission rules you create and associated with users and user groups. For more on setting permissions see [Using Permissions](security-and-auth/using-permissions.html). Each Application User is represented by a User entity in your Usergrid application. For more about the User entity, see User.
+ +## Admin authentication levels + +

WARNING


 +Warning: Safe use of admin authentication levels. Never use client ID and client secret, or any hard-coded credentials to authenticate this way from a client-side app, such as a mobile app. A hacker could analyze your app and extract the credentials for malicious use even if those credentials are compiled and in binary format. Even when authenticating with username and password, be cautious when using these authentication levels since they grant broad access to your Usergrid account. See [Security Best Practices](../security-and-auth/securing-your-app.html) for additional considerations in keeping access to your app and its data secure.

+ + + + + + + + + + + + + + + + + + +
Authentication LevelDescription
Application clientGrants full access to perform any operation on an Usergrid application (but not other applications within the same organization). + +

Authentication at this level is useful in a server-side application (not a mobile app) that needs access to resources through the Usergrid API. For example, imagine you created a website that lists every hiking trail in the Rocky Mountains. You would want anyone to be able to view the content, but would not want them to access the Usergrid API and all your data directly. Instead, you would authenticate as an application client in your server-side code to access the data via the API in order to serve it to your website's visitors.

Organization clientGrants full access to perform any operation on an Usergrid organization. + +

This authentication level provides the greatest amount of access to an individual organization, allowing a client to perform any operation on an Usergrid organization and any applications in that organization. This level of access should be used sparingly and carefully.

Admin userAllows full access to perform any operation on all organization accounts of which the admin user is a member. + +

This authentication level is useful from applications that provide organization-wide administration features. For example, the Usergrid admin portal uses this level of access because it requires full access to the administration features.

+ + Unless you have a specific need for administrative features, such as to run test scripts that require access to management functionality, you should not use the admin user authentication level.
+ + + + + + + + + + diff --git a/content/docs/_sources/security-and-auth/using-permissions.txt b/content/docs/_sources/security-and-auth/using-permissions.txt new file mode 100644 index 0000000000..1454d1132f --- /dev/null +++ b/content/docs/_sources/security-and-auth/using-permissions.txt @@ -0,0 +1,115 @@ +# Using permissions + +Permissions allow you to define user access to perform GET, POST, PUT, or DELETE operations on specific resources. When the user submits a request via your app code to the Usergrid API, the user’s permissions are checked against the resource paths that the user is trying to access. The request succeeds only if access to the resource is allowed by the permission rules you specify. + +## Permissions syntax +In Usergrid, permissions are represented in the following format: + + : + +* ````: A comma-delimited set of HTTP methods (``GET``, ``PUT``, ``POST``, ``DELETE``) that are allowed for the specified resource path. For example, ``get``, ``post`` would allow only ``GET`` and ``POST`` requests to be made to the specified resource. +* ````: The path to the resources to be accessed. For example, ``/users`` would apply the permission to the users collection, while ``/users/Tom`` would apply the permission to only the user entity with username 'Tom'. + +## Complex paths +Complex paths can be defined using [Apache Ant pattern syntax](http://ant.apache.org/manual/dirtasks.html#patterns). The following special path variables are supported for the construction of complex paths: + + + + + + + + + + + + + + + + + + +
ParameterDescription
*Treated as a wildcard. Assigns the permission to all paths at the specified level in the path hierarchy. For example, ``/*`` would match any collection, while ``/users/Tom/*`` would match /users/Tom/likes and ``/users/Tom/owns``.
**Assigns the permission to the path recursively. For example, ``**/likes`` would match ``/likes`` and ``/users/likes``, while ``/users/**`` would match ``/users`` and ``/users/likes``.
\${user}Automatically sets the path segment to the UUID of the currently authenticated user. For example, if you sent a request with a valid access token for a user with UUID ``bd397ea1-a71c-3249-8a4c-62fd53c78ce7``, the path ``/users/${user}`` would be interpreted as ``/users/bd397ea1-a71c-3249-8a4c-62fd53c78ce7``, assigning the permission only to that user entity.
+ +## Assigning permissions +Permissions can only be assigned to user, group or role entities. Assigning permissions to roles can be particularly useful, as it allows you to create sets of permissions that represent complex access definitions, which can then be assigned to user and group entities. For more on roles, see [Using Roles](security-and-auth/using-roles.html). + +### Request syntax + + curl -X POST https://api.usergrid.com/////permissions -d '{"permission":}' + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +collection The collection of the entity that the permissions are to be assigned to. +entity The UUID of the entity to assign the permissions to. For users, username and for groups, name are also accepted. +permissions The permissions to assign to the entity. See [Permissions syntax](security-and-auth/using-permissions.html#permissions-syntax) for format. + +For collections, Valid values are users and groups. + +### Example request +For example, the following cURL request would give the user 'Tom' POST permission to the /users collection: + + curl -X POST https://api.usergrid.com/your-org/your-app/users/Tom/permissions -d '{"permission":"post:/users"}' + +### Example response +The newly assigned permission is returned in the data property of the response: + + { + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "uri" : "https://api.usergrid.com/your-org/your-app", + "entities" : [ ], + "data" : [ "post:/users" ], + "timestamp" : 1402349612382, + "duration" : 19, + "organization" : "your-org", + "applicationName" : "your-app" + } + + +## Removing permissions +Using a DELETE request, you can remove one of more permissions from a user, group, or role entity. + +### Request syntax + + curl -X DELETE https://api.usergrid.com/////permissions?= + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +collection The collection of the entity that the permissions are to be assigned to. Valid values are users and groups. +entity The UUID of the entity to assign the permissions to. For users, username and for groups, name are also accepted. +permissions The permissions to assign to the entity. See [Permissions syntax](using-permissions.html) for format. + + +### Example request + + curl -X DELETE https://api.usergrid.com/your-org/your-app/users/Tom/permissions?permission=post:/users + +### Example response +The deleted permission is returned in the params.permission property of the response: + + { + "action" : "delete", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { + "permission" : [ "post:/users" ] + }, + "uri" : "https://api.usergrid.com/your-org/your-app", + "entities" : [ ], + "data" : [ "post:/assets" ], + "timestamp" : 1402349951530, + "duration" : 20, + "organization" : "your-org", + "applicationName" : "your-app" + } + \ No newline at end of file diff --git a/content/docs/_sources/security-and-auth/using-roles.txt b/content/docs/_sources/security-and-auth/using-roles.txt new file mode 100644 index 0000000000..2a794e3c56 --- /dev/null +++ b/content/docs/_sources/security-and-auth/using-roles.txt @@ -0,0 +1,304 @@ +# Using roles +Roles are named sets of one or more permissions, and are useful for defining specific access levels to resources in your Usergrid data store. Multiple roles can be assigned to a user or group, giving you a great deal of flexibility in how access to resources are defined. + +For example, in a blogging app you might create a 'reviewer' role that allows GET and PUT access to an articles collection to allow the user to retrieve and update articles, but not allow them to create new articles. + +## Default roles +While you can create as many custom roles as you want per application, all Usegrid applications include three default roles. These roles each serve a special purpose and should not be deleted; however, you can and should adjust the permissions assigned to these roles to suit the needs of you app. + +The following table describes each pre-defined role, and the permissions that are assigned to them by default. + + + + + + + + + + + + + + + + + + + + + + +
Role PermissionsDescription
Guest + +* post: /devices +* post: /users +* put: /devices/* + + + + Assigned to all unauthenticated requests. Includes a basic set of permissions that are commonly needed by unregistered or unauthenticated users. +

Grants permission for a user to create a user account and for their device to be registered. + +

Default + +* get, post, put, delete: /** + + + +Default for authenticated users. Assigns the associated permissions to all users whose requests are authenticated with a valid access token. + +

WARNING


 +By default, __grants full access for all resources in your application__. A first task in securing your application should be to restrict access by redefining this role to narrow the access it provides. Remove the default full permission rule and add restrictive permission rules for a production deployment. +

+ +
AdministratorNone + +Unused until you associate it with users or groups. By default, includes no permissions that provide access. Grants no access. Consider this a blank slate. Add permission rules and associate this role with users and groups as needed. +

NOTE


 +The Administrator role is not the same as an organization administrator, that is, someone who authenticates as an Admin User. The Admin User is an implicit user created when you create an organization. After authenticating, the Admin User has full access to all of the administration features of the Usergrid API. By comparison, the Administrator role is simply a role (initially without permissions) that can be assigned to any user. +

+ +
+ +## Creating roles +Generally, it is easiest to a create a role for each access type you want to enable in your app. You may, however, assign multiple roles to any user or group entity, so you have the flexibility to define any schema for applying roles that you like. + +The following shows how to create a new role and assign permissions to it. + +### Request syntax +With cURL requests a role entity is created with a POST request, then permissions must be assigned to it with a separate request. For more on assigning permissions with cURL, see [Using Permissions](security-and-auth/using-permissions.html). + +The following details how to create a new role entity. + + curl -X POST https://api.usergrid.com///roles -d '{"name":}' + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +roleName The name of the role to be created + +### Example request + + curl -X POST "https://api.usergrid.com/my-org/my-app/roles/ -d '{"name":"manager"}' + +### Example response + + { + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/roles", + "uri" : "https://api.usergrid.com/your-org/your-app/roles", + "entities" : [ { + "uuid" : "382d0991-74bb-3548-8166-6b07e44495ef", + "type" : "role", + "name" : "manager", + "created" : 1402612783104, + "modified" : 1402612783104, + "roleName" : "manager", + "title" : "manager", + "inactivity" : 0, + "metadata" : { + "path" : "/roles/382d0991-74bb-3548-8166-6b07e44495ef", + "sets" : { + "permissions" : "/roles/382d0991-74bb-3548-8166-6b07e44495ef/permissions" + }, + "collections" : { + "groups" : "/roles/382d0991-74bb-3548-8166-6b07e44495ef/groups", + "users" : "/roles/382d0991-74bb-3548-8166-6b07e44495ef/users" + } + } + } ], + "timestamp" : 1402612783102, + "duration" : 30, + "organization" : "your-org", + "applicationName" : "your-app" + } + + +### Creating Roles in the Admin Portal + +1. In the left sidebar of the Usergrid portal, click Users > Roles. This displays the roles defined for the application. +Click the '+' button. +2. In the dialog box, provide a 'title' and 'role name.' A title is an alias for the role name. +3. Click 'Create'. The role will be created, but will not have any permissions assigned to it. +4. Click the role you created in the list. +5. Click the 'Add permissions' button. +6. In the dialog box, click the check boxes for the HTTP methods you want to grant permissions for, and enter the resource path in the 'Path' field. +7. The 'Inactivity' field lets you control automatic user logout during periods of inactivity. Set a number of seconds of inactivity before users assigned to this role are automatically logged out. + +## Assigning roles +Once you have created some roles, you will need to explicitly assign them to a user or group entity. The permissions associated with that role will be granted to the entity immediately for any requests they send that are authenticated by a valid access token. Please note that assigning a role to a group will grant the associated permissions to every user in that group. + +The following shows how to assign a role to an entity. + +### Request syntax + + curl -X POST https://api.usergrid.com///roles/// + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +roleName The name of the role to be created +entityType The type of the entity the role is being assigned to. 'Group' and 'user' are valid values. +entityID The UUID of the entity the role is being assigned to. + +For groups, the 'name' property can be used. For users, the 'username' property can be used. + +### Example request + + curl -X POST "https://api.usergrid.com/my-org/my-app/roles/manager/users/someUser + + +### Example response + + { + "action" : "post", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users", + "uri" : "https://api.usergrid.com/your-org/your-app/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users", + "entities" : [ { + "uuid" : "410b213a-b379-11e3-a0e5-9953085ea376", + "type" : "user", + "name" : "someUser", + "created" : 1395681911491, + "modified" : 1399070010291, + "username" : "someUser", + "activated" : true, + "file" : "fobnszewobnioerabnoiawegbrn\n", + "metadata" : { + "connecting" : { + "friends" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/connecting/friends", + "likes" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/connecting/likes" + }, + "path" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376", + "sets" : { + "rolenames" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/roles", + "permissions" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/permissions" + }, + "connections" : { + "completed" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/completed", + "follows" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/follows" + }, + "collections" : { + "activities" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/activities", + "devices" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/devices", + "feed" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/feed", + "groups" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/groups", + "roles" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/roles", + "following" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/following", + "followers" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/followers" + } + } + } ], + "timestamp" : 1402965083889, + "duration" : 41, + "organization" : "your-org", + "applicationName" : "your-app" + } + + +### Assigning Roles in the Admin Portal + +The easiest way to assign roles to user or group entities is to use the 'Users' tab of the Usergrid admin portal, by doing the following: + +1. In the left sidebar of the admin portal, click Users > Users or Users > Groups to display either the list of users or groups in your application. +2. In the list, click the name of the user or group entity you want to assign roles to to display its details in the right pane. +3. Click the 'Roles & Permissions' tab above the right pane. +4. Click the 'Add Role' button. +5. In the popup, select a role from the drop down menu. +6. Click the 'Add' button. + + +## Removing roles +At times it may be necessary to remove a role from a user or group entity, for example if a user changes jobs, or the duties of a group are altered. Please note that removing a role from a group will remove the associated permissions from every user in that group. + +The following shows how to remove a role from an entity. + +### Request syntax + + curl -X DELETE https://api.usergrid.com///roles/// + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +roleName The name of the role to be created +entityType The type of the entity the role is being removed from. 'Group' and 'user' are valid values. +entityID The UUID of the entity the role is being removed from. + +For groups, the 'name' property can be used. For users, the 'username' property can be used. + +### Example request + + curl -X DELETE https://api.usergrid.com/my-org/my-app/roles/manager/users/someUser + + +### Example response + + { + "action" : "delete", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users", + "uri" : "https://api.usergrid.com/your-org/your-app/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users", + "entities" : [ { + "uuid" : "410b213a-b379-11e3-a0e5-9953085ea376", + "type" : "user", + "name" : "someUser", + "created" : 1395681911491, + "modified" : 1399070010291, + "username" : "someUser", + "activated" : true, + "metadata" : { + "connecting" : { + "friends" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/connecting/friends", + "likes" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/connecting/likes" + }, + "path" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376", + "sets" : { + "rolenames" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/roles", + "permissions" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/permissions" + }, + "connections" : { + "completed" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/completed", + "follows" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/follows" + }, + "collections" : { + "activities" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/activities", + "devices" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/devices", + "feed" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/feed", + "groups" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/groups", + "roles" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/roles", + "following" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/following", + "followers" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/followers" + } + } + } ], + "timestamp" : 1403214283808, + "duration" : 358, + "organization" : "your-org", + "applicationName" : "your-app" + } + +### Removing Roles in the Admin Portal + +The easiest way to remove roles from user or group entities is to use the 'Users' tab of the Usergrid admin portal, by doing the following: + +1. In the left sidebar of the Usergrid admin portal, click Users > Users or Users > Groups to display either the list of users or groups in your application. +2. In the list, click the name of the user or group entity you want to remove roles from to display its details in the right pane. +3. Click the 'Roles & Permissions' tab above the right pane. +4. Click the role you created in the list. +5. Under 'Roles', click the checkbox beside the role you want to remove from the entity. +6. Click the 'Leave roles' button. + \ No newline at end of file diff --git a/content/docs/_sources/user-management/activity.txt b/content/docs/_sources/user-management/activity.txt new file mode 100644 index 0000000000..4f09c8bfac --- /dev/null +++ b/content/docs/_sources/user-management/activity.txt @@ -0,0 +1,439 @@ +# Activity + +Most modern applications struggle to manage data streams, such as those +that contain an ongoing list of comments, activities, and tweets. In +particular, mobile applications are prone to generating very large +amounts of data in a data stream. Beyond that, additions to a data +stream must often be routed automatically to subscribers or filtered or +counted. + +Usergrid provides an activity entity that is specifically designed +for data streams. An activity is an entity type that represents activity +stream actions (see the [JSON Activity Streams 1.0 +specification](http://activitystrea.ms/specs/json/1.0/) for more +information about these actions). + +When a user creates an activity, it creates a relationship between the +activity and the user who created it. Because this relationship exists, +the activity will appear in the feed of any of the user’s followers. +Think of the Activities endpoint (``/users/{uuid|username}/activities``) as +an "outbox" of news items created by the user. Think of the Feed +endpoint (``/users/{uuid|username}/feed``) as an "inbox" of news items meant +to be seen or consumed by the user. + +A user can also post an activity to a group (located at +``/groups/{uuid|groupname}/activities``). This allows you to emulate +Facebook-style group functionality, where a limited number of users can +share content on a common "wall". In any of these cases, there is no +need to construct publish/subscribe relationships manually. + +Activity entities are particularly useful in applications that enable +users to post content to activity streams (also called feeds) and to +display activity streams. Some examples of these applications are +Twitter, foursquare, and Pinterest. For example, when a Twitter user +posts a short, 140-character or less, "tweet", that activity gets added +to the user's activity stream for display as well as to the activity +streams of any of the user's followers. + +Using Usergrid APIs you can create, retrieve, update, and delete +activity entities. + +__Note:__ Although not shown in the API examples below, you need to +provide a valid access token with each API call. See +[Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + + +## Posting activities + +Posting a user activity + +Use the POST method to create an activity in the activities collection. + +### Request URI + + POST ///users//activities { request body } + +Parameters + +Parameter Description +--------- ----------- +arg uuid|string org_id Organization UUID or organization name +arg uuid|string app_id Application UUID or application name +request body One or more sets of activity properties + +Here's an example request body: + + { + "actor":{ + "displayName":"John Doe", + "uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1", + "username":"john.doe", + "image":{ + "duration":0, + "height":80, + "url":"http://www.gravatar.com/avatar/","width":80}, + "email":"john.doe@gmail.com" + }, + "verb":"post", + "content":"Hello World!" + } + } + +### Example - Request + + curl -X POST "https://api.usergrid.com/my-org/my-app/users/john.doe/activities" -d '{"actor":{"displayName":"John Doe","uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1","username":"john.doe", "image":{"duration":0,"height":80,"url":"http://www.gravatar.com/avatar/","width":80}, "email":"john.doe@gmail.com"},"verb":"post","content":"Hello World!"}' + +### Example - Response + + { + "action" : "post", + "application" : "5111c463-6a42-11e1-b6dd-1231380a0284", + "params" : { + }, + "path" : "/users/1f3567aa-da83-11e1-afad-12313b01d5c1/activities", + "uri" : "https://api.usergrid.com/5111c463-6a42-11e1-b6dd-1231380a0284/users/1f3567aa-da83-11e1-afad-12313b01d5c1/activities", + "entities" : [ { + "uuid" : "da448955-f3aa-11e1-8042-12313d331ae8", + "type" : "activity", + "created" : 1346445092974, + "modified" : 1346445092974, + "actor" : { + "displayName" : "John Doe", + "uuid" : "1f3567aa-da83-11e1-afad-12313b01d5c1", + "username" : "john.doe", + "image" : { + "duration" : 0, + "height" : 80, + "url" : "http://www.gravatar.com/avatar/", + "width" : 80 + }, + "email" : "john.doe@gmail.com" + }, + "content" : "Hello World!", + "metadata" : { + "path" : "/users/1f3567aa-da83-11e1-afad-12313b01d5c1/activities/da448955-f3aa-11e1-8042-12313d331ae8" + }, + "published" : 1346445092974, + "verb" : "post" + } ], + "timestamp" : 1346445092827, + "duration" : 1406, + "organization": "my-org", + "applicationName": "my-app" + } + +__Note__: Anytime a logged-in user makes a request, you can substitute "me" for the uuid or username. So the format of a request to create an activity for the currently logged-in user would look like this: + + POST ///users/me/activities { request body } + +The ``/users/me`` endpoint is accessible only if you provide an access token with the request. If you don't provide an access token with the request, that is, you make an anonymous (or "guest") call, the system will not be able to determine which user to return as ``/users/me``. + +When you create an activity it creates a relationship between the activity and the user who created it. In other words, the newly created activity above belongs to john.doe. Another way of saying this is the user "owns" the activity. And because this relationship exists, the activity will appear in the feed of any of the user’s followers (in this example, anyone who is following john.doe). However, it will not appear in the feed of people the user follows. The activity is accessible at the ``/activities`` endpoint to users who have the permission to read that endpoint. + +Notice the properties specified in the request body in the previous example are actor, verb, and content. The actor, verb, and content properties are built into the Activity entity (see [Activity entity properties](../rest-endpoints/api-doc.html#activity) ). The actor property specifies properties of the entity that performs the action (here, user john.doe). The gravatar URL is used to create an icon for the activity. And because an Activity is simply an API Services data entity, you can also create custom properties. + +The verb parameter is descriptive. You can use it to indicate what type of activity is posted, for example, an image versus text. The value post is defined in the JSON Activity Streams specification as “the act of authoring an object and then publishing it online.“ + +## Posting an activity to a group + +Use the POST method to post an activity to a specific group. In this case the activity is created in the activities collection and is accessible at the ``/activities`` endpoint to users who have the permission to read that endpoint. In addition, a relationship is established between the activity and the group, and because of that, the activity will appear in the group’s feed. The group "owns" the activity. Also, the activity will be published in the feed of all users that are members of the group. + +### Request URI + + POST /{org_id}/{app_id}/groups/{uuid|groupname}/activities {request body} + +Parameters + +Parameter Description +--------- ----------- +arg uuid|string org_id Organization UUID or organization name +arg uuid|string app_id Application UUID or application name +arg uuid|string groupname UUID or name of the group +request body One or more sets of activity properties. + +Here's a sample request body: + + { + "actor": + { + "displayName":"John Doe", + "uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1", + "username":"john.doe", + "image":{ + "duration":0, + "height":80, + "url":"http://www.gravatar.com/avatar/","width":80}, + "email":"john.doe@gmail.com"}, + "verb":"post", + "content":"Hello World!" + } + +### Example - Request + + curl -X POST "https://api.usergrid.com/my-org/my-app/groups/mygroup/activities" -d '{"actor":{"displayName":"John Doe","uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1","username":"john.doe", "image":{"duration":0,"height":80,"url":"http://www.gravatar.com/avatar/","width":80}, "email":"john.doe@gmail.com"},"verb":"post","content":"Hello World!"}' + +Because this relationship exists, this activity will appear in the feed of all users who are members of mygroup. It won't appear in the feeds of the group members’ followers or in feeds of users they follow. + +### Example - Response + + { + "action": "post", + "application": "3400ba10-cd0c-11e1-bcf7-12313d1c4491", + "params": {}, + "path": "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/activities", + "uri": "https://api.usergrid.com/my-org/my-app/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/activities", + "entities": [ + { + "uuid": "563f5d96-37f3-11e2-a0f7-02e81ae640dc", + "type": "activity", + "created": 1353952903811, + "modified": 1353952903811, + "actor": { + "displayName": "John Doe", + "uuid": "1f3567aa-da83-11e1-afad-12313b01d5c1", + "username": "john.doe", + "image": { + "duration": 0, + "height": 80, + "url": "http://www.gravatar.com/avatar/", + "width": 80 + }, + "email": "john.doe@gmail.com" + }, + "content": "Hello World!", + "metadata": { + "path": "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/activities/563f5d96-37f3-11e2-a0f7-02e81ae640dc" + }, + "published": 1353952903811, + "verb": "post" + } + ], + "timestamp": 1353952903800, + "duration": 81, + "organization": "my-org", + "applicationName": "my-app" + } + +## Creating an activity for a user's followers in a group + +Use the POST method to create an activity that will be published only in the feeds of users who (1) follow you, and (2) are in the same group to which you posted the activity. This is useful if you want to create specific groups of friends (for example, acquaintances or colleagues) and publish content to them with more precise privacy settings. This allows you to re-create a privacy model similar to Google+’s Circles or Facebook current privacy system. + +When you create an activity for a user’s followers in a group: + +The activity is accessible at the ``/activities`` endpoint to users who have the permission to read that endpoint. The activity will not be cross-posted to the group’s activity endpoint (``/groups/{uuid|groupname}/activities``) +A relationship is automatically created between the activity entity that was just created and the user within that group (``/groups/{uuid|groupname}/users/{uuid|username}``) +The user within the group (``/groups/{uuid|groupname}/users/{uuid|username}``) becomes the owner of the activity (through the owner property in the activity). + +### Request URI + + POST /{org_id}/{app_id}/groups/{uuid|groupname}/users/{uuid|username}/activities {request body} + +Parameters + +Parameter Description +arg uuid|string org_id Organization UUID or organization name +arg uuid|string app_id Application UUID or application name +arg uuid|string groupname UUID or name of the group +arg uuid|string username UUID or name of the user +request body One or more sets of activity properties + +Example request body: + + { + "actor": + { + "displayName":"John Doe", + "uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1", + "username":"john.doe", + "image":{ + "duration":0, + "height":80, + "url":"http://www.gravatar.com/avatar/","width":80}, + "email":"john.doe@gmail.com"}, + "verb":"post", + "content":"Hello World!" + } + +### Example - Request + + curl -X POST "https://api.usergrid.com/my-org/my-app/groups/mygroup/users/john.doe/activities" -d '{"actor":{"displayName":"John Doe","uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1","username":"john.doe", "image":{"duration":0,"height":80,"url":"http://www.gravatar.com/avatar/","width":80}, "email":"john.doe@gmail.com"},"verb":"post","content":"Hello World!"}' + +Because this relationship exists, this activity will appear in the feed of all users who are members of mygroup. It won't appear in the feeds of the group members’ followers or in feeds of users they follow. + +### Example - Response + + { + "action" : "post", + "application" : "3400ba10-cd0c-11e1-bcf7-12313d1c4491", + "params" : { }, + "path" : "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/users/34e26bc9-2d00-11e2-a065-02e81ae640dc/activities", + "uri" : "https://api.usergrid.com/my-org/my-app/ + /groups/d87edec7-fc4d-11e1-9917-12313d1520f1/users/34e26bc9-2d00-11e2-a065-02e81ae640dc/activities", + "entities" : [ { + "uuid" : "2440ca58-49ff-11e2-84c0-02e81adcf3d0", + "type" : "activity", + "created" : 1355937094825, + "modified" : 1355937094825, + "actor" : { + "displayName" : "John Doe", + "uuid" : "1f3567aa-da83-11e1-afad-12313b01d5c1", + "username" : "john.doe", + "image" : { + "duration" : 0, + "height" : 80, + "url" : "http://www.gravatar.com/avatar/", + "width" : 80 + }, + "email" : "john.doe@gmail.com" + }, + "content" : "Happy New Year!", + "metadata" : { + "path" : "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/users/34e26bc9-2d00-11e2-a065-02e81ae640dc/activities/2440ca58-49ff-11e2-84c0-02e81adcf3d0" + }, + "published" : 1355937094825, + "verb" : "post" + } ], + "timestamp" : 1355937094789, + "duration" : 95, + "organization" : "my-org", + "applicationName" : "my-app" + } + +## Retrieving activity feeds + +Retrieving a user's activity feed + +Use the GET method to retrieve a user’s feed. + +### Request URI + + GET /{org_id}/{app_id}/users/{uuid|username}/feed + +### Example - Request + + curl -X GET "https://api.usergrid.com/my-org/my-app/users/john.doe/feed" + +### Example - Response + + { + "action" : "get", + "application" : "3400ba10-cd0c-11e1-bcf7-12313d1c44914", + "params" : {}, + "path" : "/users/d9693ec3-61c9-11e2-9ffc-02e81adcf3d0/feed", + "uri" : "https://api.usergrid.com/3400ba10-cd0c-11e1-bcf7-12313d1c44914/users/d9693ec3-61c9-11e2-9ffc-02e81adcf3d0/feed", + "entities" : [ { + "uuid" : "ffd79647-f399-11e1-aec3-12313b06ae01", + "type" : "activity", + "created" : 1346437854569, + "modified" : 1346437854569, + "actor" : { + "displayName" : "John Doe", + "image" : { + "duration" : 0, + "height" : 80, + "url" : "http://www.gravatar.com/avatar/", + "width" : 80 + }, + "uuid" : "d9693ec3-61c9-11e2-9ffc-02e81adcf3d0", + "email" : "john.doe@gmail.com", + "username" : "john.doe" + }, + "content" : "Hello World!", + "metadata" : { + "cursor" : "gGkAAQMAgGkABgE5ffM1aQCAdQAQ_9eWR_OZEeGuwxIxOwauAQCAdQAQABlaOvOaEeGuwxIxOwauAQA", + "path" : "/users/d9693ec3-61c9-11e2-9ffc-02e81adcf3d0/feed/ffd79647-f399-11e1-aec3-12313b06ae01" + }, + "published" : 1346437854569, + "verb" : "post" + }, { + "uuid" : "2482a1c5-e7d0-11e1-96f6-12313b06d112", + "type" : "activity", + "created" : 1345141694958, + "modified" : 1345141694958, + "actor" : { + "displayName" : "moab", + "image" : { + "duration" : 0, + "height" : 80, + "url" : "http://www.gravatar.com/avatar/", + "width" : 80 + }, + "uuid" : "d9693ec3-61c9-11e2-9ffc-02e81adcf3d0", + "email" : "massoddb@mfdsadfdsaoabl.com", + "username" : "moab" + }, + "content" : "checking in code left and right!!", + "metadata" : { + "cursor" : "gGkAAQMAgGkABgE5MLFh7gCAdQAQJIKhxefQEeGW9hIxOwbREgCAdQAQJNEP6ufQEeGW9hIxOwbREgA", + "path" : "/users/d9693ec3-61c9-11e2-9ffc-02e81adcf3d0/feed/2482a1c5-e7d0-11e1-96f6-12313b06d112" + }, + "published" : 1345141694958, + "verb" : "post" + } ], + "timestamp" : 1346438331316, + "duration" : 144, + "organization": "my-org", + "applicationName": "my-app" + } + +## Retrieving a group's activity feed + +Use the GET method to retrieve the feed for a group. This gets a list of all the activities that have been posted to this group, that is, the activities for which this group has a relationship (owns). + +### Request URI + + GET /{org_id}/{app_id}/groups/{uuid|groupname}/feed + +Parameters + +Parameter Description +--------- ----------- +arg uuid|string org_id Organization UUID or organization name +arg uuid|string app_id Application UUID or application name +arg uuid|string groupname UUID or name of the group + +### Example - Request + + curl -X GET "https://api.usergrid.com/my-org/my-app/groups/mygroup/feed" + +### Example - Response + + { + "action": "get", + "application": "3400ba10-cd0c-11e1-bcf7-12313d1c4491", + "params": {}, + "path": "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/feed", + "uri": "https://api.usergrid.com/my-org/my-app/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/feed", + "entities": [ + { + "uuid": "563f5d96-37f3-11e2-a0f7-02e81ae640dc", + "type": "activity", + "created": 1353952903811, + "modified": 1353952903811, + "actor": { + "displayName": "John Doe", + "image": { + "duration": 0, + "height": 80, + "url": "http://www.gravatar.com/avatar/", + "width": 80 + }, + "uuid": "1f3567aa-da83-11e1-afad-12313b01d5c1", + "email": "john.doe@gmail.com", + "username": "john.doe" + }, + "content": "Hello World!", + "metadata": { + "cursor": "gGkAAQMAgGkABgE7PeHCgwCAdQAQVj9dljfzEeKg9wLoGuZA3ACAdQAQVkVRCTfzEeKg9wLoGuZA3AA", + "path": "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/feed/563f5d96-37f3-11e2-a0f7-02e81ae640dc" + }, + "published": 1353952903811, + "verb": "post" + } + ], + "timestamp": 1353953272756, + "duration": 29, + "organization": "my-org", + "applicationName": "my-app" + } + \ No newline at end of file diff --git a/content/docs/_sources/user-management/group.txt b/content/docs/_sources/user-management/group.txt new file mode 100644 index 0000000000..a48606b87a --- /dev/null +++ b/content/docs/_sources/user-management/group.txt @@ -0,0 +1,363 @@ +# Working with group data + +You can organize app users into groups. Groups have their own Activity Feed, their own permissions and be a useful alternative to Roles, depending on how you model your data. Groups were originally designed to emulate Facebook Groups, so they will tend to function about the same way Facebook Groups would. + +Groups are hierarchical. Every member of the group ``/groups/california/san-francisco`` is also a member of the group ``/groups/california``. + +Groups are also a great way to model things such a topic subscriptions. For example, you could allow people to subscribe (i.e. become a member of the group and be alerted via Activities) to ``/groups/memes/dogs/doge`` or subscribe to all ``/groups/memes/dogs``. + +See the [Group Model section of the API Reference](../rest-endpoints/api-docs.html#group) for a list of the system-defined properties for group entities. In addition, you can create group properties specific to your application. + +## Creating groups + +A group entity represents an application group of users. You can create, retrieve, update, delete, and query group entities. See [User entity properties](../rest-endpoints/api-doc.html#user) for a list of the system-defined properties for group entities. In addition, you can create group properties specific to your application. + +### Request Syntax + + curl -X POST "https://api.usergrid.com/your-org/your-app/groups" '{ request body }' + +Use the POST method to create a new group. Groups use paths to indicate their unique names. This allows you to create group hierarchies by using slashes. For this reason, you need to specify a path property for a new group. + +### Request URI + + POST /{org_id}/{app_id}/groups + +Parameters + +Parameter Description +--------- ----------- +uuid | org_id Organization UUID or organization name +uuid | app_id Application UUID or application name +request body One or more sets of group properties of which path is mandatory. + +The ``path`` property is required and must be unique, it may include forward slashes to denote hierarchical relationships. + + { + "path" : "somegroup/somesubgroup", + "title" : "Some SubGroup" + } + +### Example + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Request + + curl -X POST "https://api.usergrid.com/my-org/my-app/groups" -d '{"path":"mynewgroup"}' + +### Response + + { + "action": "post", + "application": "7fb8d891-477d-11e1-b2bd-22000a1c4e22", + "params": {}, + "path": "/groups", + "uri": "https://api.usergrid.com/22000a1c4e22-7fb8d891-477d-11e1-b2bd/7fb8d891-477d-11e1-b2bd-22000a1c4e22/groups", + "entities": [{ + "uuid": "a668717b-67cb-11e1-8223-12313d14bde7", + "type": "group", + "created": 1331066016571, + "modified": 1331066016571, + "metadata": { + "path": "/groups/a668717b-67cb-11e1-8223-12313d14bde7", + "sets": { + "rolenames": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/rolenames", + "permissions": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/permissions" + }, + "collections": { + "activities": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/activities", + "feed": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/feed", + "roles": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/roles", + "users": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users" + } + }, + "path": "mynewgroup" + }], + "timestamp": 1331066016563, + "duration": 35, + "organization": "my-org", + "applicationName": "my-app" + } + +## Retrieving groups + +Retrieving group data + +You can retrieve data about groups through cURL or one of the SDKs. Each provides a way to filter the list of groups by data associated with the group, such as title or path, or other properties in the group entity. + +See the [Group Model section of the API Reference](../rest-endpoints/api-docs.html#group) for a list of the system-defined properties for group entities. In addition, you can create group properties specific to your application. + +### Request Syntax + + curl -X GET "https://api.usergrid.com/my-org/my-app/groups/mynewgroup" + +Use the GET method to retrieve group data. + +### Request URI + + GET ///groups | + +Parameters + +Parameter Description +--------- +org_id | uuid Organization UUID or organization name +app_id | uuid Application UUID or application name +groupPath | uuid Group UUID or group path, which must be unique. +query_string A data store query. For more on queries, see [Data queries](../data-queries/querying-your-data.html). + +### Request + + # Get a group by the group path, "employees/managers". + curl -X GET "https://api.usergrid.com/my-org/my-app/groups/employees/managers" + + # Get a group by UUID. + curl -X GET "https://api.usergrid.com/my-org/my-app/groups/a407b1e7-58e8-11e1-ac46-22000a1c5a67e" + + # Get group data filtering by their title. + curl -X GET "https://api.usergrid.com/my-org/my-app/groups?ql=select%20*%20where%20title%3D'Management%20Employees'" + +### Response + +The following is an example of JSON returned by a query for a single group. + + { + "action" : "get", + "application" : "db1e60a0-417f-11e3-9586-0f1ff3650d20", + "params" : { }, + "path" : "/groups", + "uri" : "https://api.usergrid.com/steventraut/mynewapp/groups", + "entities" : [ { + "uuid" : "5005a0fa-6916-11e3-9c1b-b77ec8addc0d", + "type" : "group", + "created" : 1387503030399, + "modified" : 1387503030399, + "path" : "managers", + "metadata" : { + "path" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d", + "sets" : { + "rolenames" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/roles", + "permissions" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/permissions" + }, + "collections" : { + "activities" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/activities", + "feed" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/feed", + "roles" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/roles", + "users" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/users" + } + }, + "title" : "Management Employees" + } ], + "timestamp" : 1391020491701, + "duration" : 15, + "organization" : "my-org", + "applicationName" : "my-app" + } + +## Retrieving a group's users + +Use the GET method to retrieve all the users in a group. + +### Request URI + + GET /{org_id}/{app_id}/groups/{uuid|groupname}/users + +### Parameters + +Parameter Description +--------- -------------- +arg uuid|string org_id Organization UUID or organization name +arg uuid|string app_id Application UUID or application name +arg uuid|string groupname UUID or name of the group + +### Example - Request + + curl -X GET "https://api.usergrid.com/my-org/my-app/groups/mygroup/users" + +### Example - Response + + { + "action" : "get", + "application" : "e7127751-6985-11e2-8078-02e81aeb2129", + "params" : { }, + "path" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users", + "uri" : "http://api.usergrid.com/myorg/sandbox/groups/d20976ff-802f-11e2-b690-02e81ae61238/users", + "entities" : [ { + "uuid" : "cd789b00-698b-11e2-a6e3-02e81ae236e9", + "type" : "user", + "name" : "barney", + "created" : 1359405994314, + "modified" : 1361894320470, + "activated" : true, + "email" : "barney@apigee.com", + "metadata" : { + "path" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9", + "sets" : { + "rolenames" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/rolenames", + "permissions" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/permissions" + }, + "collections" : { + "activities" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/activities", + "devices" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/devices", + "feed" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/feed", + "groups" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/groups", + "roles" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/roles", + "following" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/following", + "followers" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/followers" + } + }, + "name" : "barney", + "picture" : "http://www.gravatar.com/avatar/00767101f6b4f2cf5d02ed510dbcf0b4", + "test" : "fred", + "username" : "barney" + } ], + "timestamp" : 1361903248398, + "duration" : 24, + "organization" : "myorg", + "applicationName" : "sandbox" + } + +## Deleting a group + +To delete a group, delete the associated group entity as you would any other entity. Note that this will only delete the group. Any entities in the group will be preserved. + +For more information and code samples, see [Deleting Data Entities](../data-storage/entities.html#deleting-data-entities). + +## Adding a user to a group + +You can add users to groups from client code using cURL commands or one of the SDKs, as described here. + +When setting up your application on the server, you might find it easier and more convenient to create and populate groups with the admin portal. There, you can create groups, create roles, and define permission rules that govern user access to data and services in your application. For more information, see [Security & Token Authentication](../security-and-auth/app-security.html). + +Use the POST method to add a user to a group. If the named group does not yet exist, an error message is returned. + +### Request syntax + + curl -X POST https://api.usergrid.com///groups//users/ + +### Request URI + + POST ///groups//users/ + +Parameters + +Parameter Description +--------- ----------- +arg uuid | string org_id Organization UUID or organization name +arg uuid | string app_id Application UUID or application name +arg uuid | string groupname UUID or name of the group +arg uuid | string username UUID or username of user + +### Example + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Request + + curl -X POST "https://api.usergrid.com/my-org/my-app/groups/mynewgroup/users/john.doe" + +### Response + + { + "action": "post", + "application": "7fb8d891-477d-11e1-b2bd-22000a1c4e22", + "params": {}, + "path": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users", + "uri": "https://api.usergrid.com/22000a1c4e22-7fb8d891-477d-11e1-b2bd/7fb8d891-477d-11e1-b2bd-22000a1c4e22/groups/a668717b-67cb-11e1-8223-12313d14bde7/users", + "entities": [{ + "uuid": "6fbc8157-4786-11e1-b2bd-22000a1c4e22", + "type": "user", + "name": "John Doe", + "created": 1327517852364015, + "modified": 1327517852364015, + "activated": true, + "email": "john.doe@mail.com", + "metadata": { + "connecting": { + "owners":"/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/connecting/owners" + }, + "path": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22", + "sets": { + "rolenames": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/rolenames", + "permissions": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/permissions" + }, + "collections":{ + "activities":"/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/activities", + "devices": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/devices", + "feed":"/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/feed", + "groups": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/groups", + "roles":"/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/roles", + "following": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/following", + "followers": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/followers" + } + }, + "picture": "https://www.gravatar.com/avatar/90f823ba15655b8cc8e3b4d63377576f", + "username": "john.doe" + }], + "timestamp": 1331066031380, + "duration": 64, + "organization" : "my-org", + "applicationName": "my-app" + } + +## Removing a user from a group + +Use the DELETE method to remove a user from the specified group. + +### Request syntax + + curl -X DELETE https://api.usergrid.com///groups//users/" + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +group UUID or name of the group +user UUID, username or email of user to be deleted + +### Example request + + curl -X DELETE https://api.usergrid.com/your-org/your-app/groups/someGroup/users/someUser + +### Example response + + { + "action" : "delete", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users", + "uri" : "https://api.usergrid.com/your-org/your-app/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users", + "entities" : [ { + "uuid" : "74d2d7da-e694-11e3-b0c6-4d2664c8e0c3", + "type" : "user", + "name" : "someUser", + "created" : 1401301104077, + "modified" : 1401301104077, + "username" : "someUser", + "email" : "your-org@apigee.com", + "activated" : true, + "picture" : "http://www.gravatar.com/avatar/0455fc92de2636fc7a176cc5d298bb78", + "metadata" : { + "path" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3", + "sets" : { + "rolenames" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/roles", + "permissions" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/permissions" + }, + "collections" : { + "activities" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/activities", + "devices" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/devices", + "feed" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/feed", + "groups" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/groups", + "roles" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/roles", + "following" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/following", + "followers" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/followers" + } + } + } ], + "timestamp" : 1401751485776, + "duration" : 220, + "organization" : "your-org", + "applicationName" : "your-app" + } diff --git a/content/docs/_sources/user-management/groups.txt b/content/docs/_sources/user-management/groups.txt new file mode 100644 index 0000000000..04bed265ea --- /dev/null +++ b/content/docs/_sources/user-management/groups.txt @@ -0,0 +1,38 @@ +# Groups + +You can organize app users into groups. Groups have their own Activity Feed, their own permissions and be a useful alternative to Roles, depending on how you model your data. Groups were originaly designed to emulate Facebook Groups, so they will tend to function about the same way Facebook Groups would. + +Groups are hierarchical. Every member of the group /groups/california/san-francisco is also a member of the group /groups/california. + +Groups are also a great way to model things such a topic subscriptions. For example, you could allow people to subscribe (i.e. become a member of the group and be alerted via Activities) to /groups/memes/dogs/doge or subscribe to all /groups/memes/dogs + + +### General properties + + Property Type Description + ---------- -------- --------------------------------------------------------------------------------- + uuid UUID Group’s unique entity ID + type string Type of entity, in this case “user” + created long [UNIX timestamp](http://en.wikipedia.org/wiki/Unix_time) of entity creation + modified long [UNIX timestamp](http://en.wikipedia.org/wiki/Unix_time) of entity modification + path string Valid slash-delimited group path (mandatory) + title string Display name + +### Set properties + + Set Type Description + ------------- -------- --------------------------------------- + connections string Set of connection types (e.g., likes) + rolenames string Set of roles assigned to a group + credentials string Set of group credentials + +### Collections + + Collection Type Description + ------------ ---------- ------------------------------------------------------ + users user Collection of users in the group + activities activity Collection of activities a user has performed + feed activity Inbox of activity notifications a group has received + roles role Set of roles to which a group belongs + +  diff --git a/content/docs/_sources/user-management/messagee-example.txt b/content/docs/_sources/user-management/messagee-example.txt new file mode 100644 index 0000000000..e3f3a02f29 --- /dev/null +++ b/content/docs/_sources/user-management/messagee-example.txt @@ -0,0 +1,137 @@ +# App Example - Messagee + +Messagee is a simple Twitter-style messaging application that leverages the extensive functionality of Usergrid. This section describes some of the features of Messagee. + +There are three client versions of Messagee: + +* [An iOS client version](https://github.com/apigee/usergrid-sample-ios-messagee) +* [An Android client version](https://github.com/apigee/usergrid-sample-android-messagee) +* [An HTML5 client](https://github.com/apigee/usergrid-sample-html5-messagee) + +The sections below describe how to create a new app, enter some test users, and run the app. You also learn how to use the Usergrid admin portal, a user interface that streamlines data and application management in the Usergrid system. The portal is also a reference application that shows how to incorporate Usergrid APIs with JavaScript. + +## Creating a user account in Usergrid + +Go to the Usergrid portal and login. If you are new to Usergrid, sign up for an account, specifying an organization (e.g., the name of your company or project team) and a username and password that you can use to authenticate. Because Usergrid are designed for use by development teams, the same username can be associated with one or more organizations. + +If you create a new account, you receive a confirmation email that contains a URL that you must click to activate the account. After this, simply log in to the portal with your username and password. + +.. image:: login.png + +## Creating an app and users + +When you have logged in, you need to create a new application. + +.. image:: portal1.png + +### STEP 1 + +Enter a unique application name. The name must be unique to avoid a conflict with another user running the same application. + +.. image:: portal2.png + +### STEP 2 + +Make sure that the portal shows the application name you entered as the active application beneath the Applications menu (1). + +If the correct name is not displayed, click the menu and select your application. Next, you need to populate a test user user-test-1 that is going to log in to your copy of the server-side Messagee app. + +### STEP 3 + +Click the Users box on the left side of the console (2). + +.. image:: portal3.png + +### STEP 4 + +Click the Add button and enter the user information for your application in the pop-up window (be sure to create a password you can remember), and then click the Create button. Repeat these steps to create a second username test-user-2. + +.. image:: portal4.png + +### STEP 5 + +When you have finished all these steps, you have a new application and two new users. + +.. image:: portal5.png + +Now that you have created a uniquely named copy of the Messagee application as well as two user accounts (test-user-1 and test-user-2), you are ready to test out the Messagee app. Use test-user-1 to log in to the app, and test-user-2 as the user to follow. + +To continue with the example, follow the instructions for a client app (iOS client, Android client, or HTML5 client). + +## iOS client + +Messagee is available as an iPhone app that uses Usergrid and RestKit. The source for the iOS version of Messagee is available in the /samples/messagee directory of the Usergrid iOS SDK + +Here are the steps to run the Messagee app on iOS: + +### STEP 6 + +Run Steps 1-5 under Creating an app and users. These steps create a unique instance of the Messagee app on the server and two test users, test-user-1 and test-user-2. + +### STEP 7 + +Access the Messagee server app by typing a URL similar to the following into your iOS mobile client (replace with the unique name of your application): +https://api.usergrid.com//index.html + +.. image:: iOS1chooseapp.jpg + +### STEP 8 + +On the mobile client, complete the registration information and click Register. + +.. image:: iOS2register.jpg + +### STEP 9 + +Log in to the Messagee app by entering the test-user-1 account information created previously, and click the Sign in button. + +.. image:: iOS3signin.jpg + +### STEP 10 + +At this point, the message board is empty: + +.. image:: iOS5emptyfeed.jpg + +### STEP 11 + +To post a message using the app, click the top-right icon in the message board to create a message, write the message text, and send it by clicking Post. + +.. image:: iOS6newmsg.jpg + +Note: The posted message should appear in the message board within few seconds. + +.. image:: iOS7feed1msg.jpg + +### STEP 12 + +For your instance of the Messagee application to act like Twitter, you need to "follow" another user. + +In the message board, click Add People and add test-user-2 as a person that test-user-1 follows. + +.. image:: iOS9followme.jpg + +### STEP 6 + +Log in as test-user-2 and post a message as this user to the message board. + +Go back and log in as user test-user-1. +Because test-user-1 follows test-user-2, you should see the message sent by test-user-2 in the message board. + +.. image:: iOS10seeusermsg.jpg + +## iOS SDK + +If you want to write iOS applications that connect to Usergrid, [download the Usergrid iOS SDK](https://github.com/apache/usergrid/tree/master/sdks/ios). + +__Note__: The Messagee iOS application uses RestKit, a popular REST framework for iOS, to communicate with Usergrid. Because Usergrid use a REST API, you can use any REST framework to talk with the service. However, the official Usergrid iOS SDK provides a more convenient communication mechanism that you should use unless you're already using RestKit or some other framework in your project. + +## Android client and SDK +Messagee is available as a sample Android app that acts as a Usergrid client. The source for the Android version is packaged with the Usergrid Android SDK in the /samples/messagee directory. + +[Download the Usergrid Android SDK](https://github.com/apache/usergrid/tree/master/sdks/android) + +## Javascript/HTML5 client and SDK +Messagee is also available as a sample HTML5 app that behaves in much the same way as the two previous examples. The source for the HTML5 version is packaged with the Usergrid Javascript/HTML5 SDK in the /samples/messagee directory. + +[Download the Usergrid Javascript/HTML5 SDK](https://github.com/apache/usergrid/tree/master/sdks/html5-javascript) diff --git a/content/docs/_sources/user-management/user-connections.txt b/content/docs/_sources/user-management/user-connections.txt new file mode 100644 index 0000000000..a386d2aebe --- /dev/null +++ b/content/docs/_sources/user-management/user-connections.txt @@ -0,0 +1,40 @@ +# Social Graph Connections + +One of the most useful features of Usergrid is the ability to create connections between entities, which allow you to model arbitrary relationships between entities. This feature is particularly powerful when applied to user entities by allowing you to model complex social graphs between users as well as groups of users. + +## Following/followers +To make the social graph possibilities of entity connections even easier to achieve, Usergrid also has special support for a default following/followers relationship, which offers these additional features: + +Reciprocal connection: If a following connection is made between a user and another user, a reciprocal followers relationship will be created automatically. In contrast, all of other entity connections are one-way, meaning any reciprocal relationship must be created manually. + +Activity feed subscription: The followed user's activities will automatically be posted to the following user's activity feed. For example, if Arthur is following Ford, then any activities published by Ford that Arthur is allowed to see will appear in Arthur's activity feed. + +## Creating a following/followers connection +To create a following/followers connection between two entities, create the connection as you would any generic entity connection. For full details on creating connections, see [Connecting entities](../entity-connections/connecting-entities.html). + +For example, the following request would create a following/followers relationship between two user entities with the usernames 'Fred' and 'Barney': + + POST https://api.usergrid.com/your-org/your-app/users/barney/following/users/fred + +

Note

+Please note that this only works when you ``POST`` a ``following`` connection. Creating a follower connection would not create a reciprocal following connection. +

+ +This would retrieve a list of the users that Barney is following: + + GET https://api.usergrid.com/your-org/your-app/users/barney/following + +And this would retrieve a list of users that are following Fred: + + GET https://api.usergrid.com/your-org/your-app/users/fred/followers + +# Creating other connections +You can extend this connection structure to create connections using any relationship. For example, you could use likes to denote a connection between a user and his dog with this POST: + + POST https://api.usergrid.com/your-org/your-app/users/Fred/likes/dogs/Dino + +Note that in this case a reciprocal connection is not automatically created. To do so you would need to manually create the reciprocal connection with another POST such as: + + POST https://api.usergrid.com/your-org/your-app/dogs/Dino/liked_by/users/Fred + +For more information on using entity connections, see [Connecting entities](../entity-connections/connecting-entities.html). diff --git a/content/docs/_sources/user-management/user-management.txt b/content/docs/_sources/user-management/user-management.txt new file mode 100644 index 0000000000..7f9e1d6a5f --- /dev/null +++ b/content/docs/_sources/user-management/user-management.txt @@ -0,0 +1,42 @@ +# User management & social graph +Whether you're developing apps for mobile or the Web, it's almost certain that you will need to be able to handle user management, as well as offer the types of social features users have come to expect from a rich app experience. Usergrid makes all of this easy with default entity types and functionality available right out of the box. From user registration and profiles to login and authentication to activity feeds and social graph, you can create a social experience quickly and easily with just a few types of API calls. + +## User management +The default user entity in Usergrid is designed to model app users, meaning registering users and managing their profiles is as simple as sending and updating JSON via the API. Used in conjunction with our available social graph, as well as our OAuth 2.0 authentication and token authorization features, you have all the tools you need to manage your user base. + +Learn more about: + +* [User management](user-management.html) +* [Authentication & tokens](../security-and-auth/app-security.html) +* [Permissions and roles](../security-and-auth/using-permissions.html) + +## Group management +One of the most basic social features of any app is the ability to create groups of users to limit shared access to user or other app data. The default group entity in Usergrid was designed for this exact purpose. Associate a user with as many groups or sub-groups as you need, then apply permissions or roles to define shared access to Usergrid data. + +Learn more about: + +* [Group management](group.md) +* [Permissions and roles](../security-and-auth/using-permissions.html) + +## Social connections +To create a rich social graph, your app needs to be able to create connections between users. Usergrid makes this process lightweight by allowing you to create social connections and generic entity connections between users to model relationships by working with simple URI paths. + +For example, you could create a 'likes' relationship between two users with a POST: + + https://api.usergrid.com/your-org/your-app/users/Arthur/likes/users/Ford + +You could then retrieve all the users Arthur 'likes' with a GET to populate a list in your UI: + + https://api.usergrid.com/your-org/your-app/users/Arthur/likes + +Learn more about: + +* [Social connections](user-connections.html) +* [Generic entity connections](../data-storage/relationship.html) + +## Activity feeds +Activity feeds can be an essential way of establishing a social dimension of your user experience. Allow users to actively publish activities, such as status messages, or have your application code passively publish activities based on user actions, such as posting a photo. Activity feeds can be created and shared at both the user and group level, giving you the flexibility to present activity feeds that are most relevant to your users. + +Learn more about: + +* [Activity feeds] diff --git a/content/docs/_sources/user-management/working-user-data.txt b/content/docs/_sources/user-management/working-user-data.txt new file mode 100644 index 0000000000..5e2b63da50 --- /dev/null +++ b/content/docs/_sources/user-management/working-user-data.txt @@ -0,0 +1,278 @@ +# Working with User Data +You can store and manage user data as User entities. With user data in your application, you can add support for a wide variety of features common to mobile apps. For example, you can: + +* Control access to data by defining permission rules. (See [Security & token authentication](../security-and-auth/app-security.html) for more.) +* Present content specific to each user, such as their list of favorites. +* Support social features, such as letting users "follow" one another, for example. + +In mobile applications, data about users is typically added by users themselves when they register through your app. The topics in this section provide specific cURL and SDK-specific examples for getting things done with user data. + +## Creating users + +A user entity represents an application user. Using API Services you can create, retrieve, update, delete, and query user entities. See [User entity properties](../rest-endpoints/api-doc.html#user) for a list of the system-defined properties for user entities. In addition, you can create user properties specific to your application. + +### Request Syntax + + curl -X POST "https://api.usergrid.com/your-org/your-app/users" -d '{ "username": "john.doe", "email": "john.doe@gmail.com", "name": "John Doe", "password": "test1234" }' + +Use the POST method to create a new user in the users collection. + +### Request URI + + POST ///users + +Parameters + +Parameter Description +--------- ----------- +uuid | org_id Organization UUID or organization name. +uuid | app_id Application UUID or application name. +request body One or more sets of user properties. + +The username is mandatory and must be unique. Here's an example: + + { + "username" : "john.doe", + "email" : "john.doe@gmail.com", + "name" : "John Doe", + "password" : "test1234" + } + +Although the password parameter is not mandatory, if you don't specify it, the user will not be able to log in using username and password credentials. If a password is not specified for the user, and you're an Admin, you can set a password for the user (see [Changing a User Password](#changing-a-user-password)). + +__ Note__: The username can contain any combination of characters, including those that represent letters, numbers, and symbols. + +### Example + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +### Request + + curl -X POST "https://api.usergrid.com/my-org/my-app/users" -d '{"username":"john.doe","email":"john.doe@gmail.com","name":"John Doe"}' + +### Response + + { + "action" : "post", + "application" : "db1e60a0-417f-11e3-9586-0f1ff3650d20", + "params" : { }, + "path" : "/users", + "uri" : "https://api.usergrid.com/steventraut/mynewapp/users", + "entities" : [ { + "uuid" : "8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc", + "type" : "user", + "name" : "John Doe", + "created" : 1390533228622, + "modified" : 1390533228622, + "username" : "john.doe", + "email" : "john.doe@gmail.com", + "activated" : true, + "picture" : "http://www.gravatar.com/avatar/e13743a7f1db7f4246badd6fd6ff54ff", + "metadata" : { + "path" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc", + "sets" : { + "rolenames" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/roles", + "permissions" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/permissions" + }, + "collections" : { + "activities" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/activities", + "devices" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/devices", + "feed" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/feed", + "groups" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/groups", + "roles" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/roles", + "following" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/following", + "followers" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/followers" + } + } + }], + "timestamp" : 1390533228619, + "duration" : 142, + "organization" : "my-org", + "applicationName" : "my-app" + } + + +## Retrieving user data + +You can retrieve data about users through cURL or one of the SDKs. Each provides a way to filter the list of users by data associated with the user, such as username or UUID, or other properties in the user entity. + +See [User entity properties](../rest-endpoints/api-doc.html#user) for a list of the system-defined properties for user entities. In addition, you can create user properties specific to your application. + +### Request Syntax + + curl -X GET "https://api.usergrid.com/your-org/your-app/users" + +Use the GET method to retrieve user data. + +### Request URI + + GET ///users/ + +Parameters + +Parameter Description +--------- ----------- +uuid | org_id Organization UUID or organization name +uuid | app_id Application UUID or application name +user identifier User UUID, username, or email address. + +The alias ``/users/me`` can be used in place of the current user’s uuid, username, or email address. Note: The ``/users/me`` endpoint is accessible only if you provide an access token with the request (see [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html)). If you make an anonymous ("guest") call, the system will not be able to determine which user to return as ``/users/me``. + +__Note__: The username can contain any combination of characters, including those that represent letters, numbers, and symbols. + +### Example + +__Note__: Although not shown in the API examples below, you need to provide a valid access token with each API call. See [Authenticating users and application clients](../security-and-auth/authenticating-users-and-application-clients.html) for details. + +Requests + + # Get a user by username. + curl -X GET "https://api.usergrid.com/my-org/my-app/users/jane.doe" + + # Get a user by UUID. + curl -X GET "https://api.usergrid.com/my-org/my-app/users/a407b1e7-58e8-11e1-ac46-22000a1c5a67e" + + # Get a user by email. + curl -X GET "https://api.usergrid.com/my-org/my-app/users/jane.doe@gmail.com" + + # Get user data filtering by their city property value. + curl -X GET "https://api.usergrid.com/my-org/my-app/users?ql=select%20*%20where%20adr.city%3D'Chicago'" + +Response + + { + "action" : "get", + "application" : "1c8f60e4-da67-11e0-b93d-12313f0204bb8", + "params" : { + "_": [ + "1315524419746" + ] + }, + "path" : "https://api.usergrid.com/12313f0204bb-1c8f60e4-da67-11e0-b93d/1c8f60e4-da67-11e0-b93d-12313f0204bb/users", + "uri" : "https://api.usergrid.com/005056c00008-4353136f-e978-11e0-8264/4353136f-e978-11e0-8264-005056c00008/users", + "entities" : [ { + "uuid" : "78c54a82-da71-11e0-b93d-12313f0204b", + "type" : "user", + "created" : 1315524171347008, + "modified" : 1315524171347008, + "activated" : true, + "email" : "jane.doe@gmail.com", + "metadata" : { + "path" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb", + "sets" : { + "rolenames" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/rolenames", + "permissions" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/permissions" + }, + "collections" : { + "activities" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/activities", + "devices" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/devices", + "feed" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/feed", + "groups" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/groups", + "roles" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/roles", + "following" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/following", + "followers" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/followers" + } + }, + "username" : "jane.doe" + } + ... Additional entities here if data for multiple users was returned... + ], + "timestamp" : 1315524421071, + "duration" : 107, + "organization" : "my-org", + "applicationName": "my-app" + } + +## Updating & deleting user data + +To update or delete a user, perform an update or delete on the associated user entity as you would any other entity. For more information and code samples, see [Updating Data Entities](../data-storage/entities.html#updating-data-entities) and [Deleting Data Entities](../data-storage/entities.html#deleting-data-entities). + +## Changing a user password + +Changing a user's password + +### Request syntax + + curl -X PUT https://api.usergrid.com///users//password -d '{oldpassword:,newpassword:}' + +Parameters + +Parameter Description +--------- ----------- +org Organization UUID or organization name +app Application UUID or application name +username_or_email Username or email of the user entity whose password you want to reset. +old_password User entity's old password. +new_password User entity's new password. + +__Note__: If your request is authenticated with an application-level token, then ``old_password`` is not required. For more, see [Application client authentication](../security-and-auth/authenticating-users-and-application-clients.html#application-client-authentication). + +Example request + + curl -X PUT https://api.usergrid.com/my-org/my-app/users/john.doe/password -d '{"newpassword":"foo9876a","oldpassword":"bar1234b"}' + +Example response + + { + "action": "set user password", + "timestamp": 1355185897894, + "duration": 47 + } + +## Resetting a user password + +Resetting a user's password + +Usergrid provides a standard password reset flow that can be implemented to allow a user to reset their password without having to provide their old password. The most common use of this would be a 'Forgot password?' feature in your app. + +Note that you can also implement your own password reset flow using application-level authentication and the /password endpoint. For more, see [Changing a user password](#changing-a-user-password). + +To use the Usergrid password reset flow, do the following: + +### STEP 1: Get the password reset request form. + +Make a GET request to the following: + + /users//resetpw + +For example, using cURL, a request to reset the password for a user with username 'someUser' would look like this: + + curl -x GET https://api.usergrid.com/your-org/your-app/users/someUser/resetpw + +### STEP 2: Display the returned password reset request form to the user. + +The request to ``/resetpw`` will return the HTML for the standard Usergrid password reset request form that you will display to your user. The request form requires the users to provide their username as well as answer a standard CAPTCHA challenge: + + + + + + Reset Password + + + +
+ +
+
+

+ Enter the captcha to have your password reset instructions sent to + someUser@adomain.com +

+

+ + +

+ +

+
+
+
+ + + +You can apply any additional styling you wish to the form to make it match the style of your app before displaying it to the user. + +### STEP 3: Let Usergrid handle the rest! + +Once the user submits the form with their username, they will receive an email from Usergrid that contains a link to the password reset form, where they can specify a new password. The user entity will be updated immediately. diff --git a/content/docs/_sources/using-usergrid/creating-a-new-application.txt b/content/docs/_sources/using-usergrid/creating-a-new-application.txt new file mode 100644 index 0000000000..ce5fb7a829 --- /dev/null +++ b/content/docs/_sources/using-usergrid/creating-a-new-application.txt @@ -0,0 +1,16 @@ +# Creating a new application + +## Creating an application +You can use the admin portal to create applications. An application represents the data associated with your app. Through an application, you handle the entities associated with your app, including users, devices, events, and so on. + +To create a new application with the admin portal: + +1. In the admin portal, from the dropdown menu at the far top left, select the organization to which you will add the new application. +1. Click the ADD NEW APP button, located at the top of the screen, next to the application drop-down. +1. In the dialog box, enter a new application name, then click the Create button. Your new application will automatically be selected in the applications drop-down menu. + +Applications can also be created programatically with a ``POST`` request to the API. For more, see [Application](../orgs-and-apps/application.html). + +## Securing an application +If this is going to be a production application, be sure to configure security roles that provide only the level of access your users will need. For more on security, see [Security Best Practices](../security-and-auth/securing-your-app.html) +. \ No newline at end of file diff --git a/content/docs/_sources/using-usergrid/creating-account.txt b/content/docs/_sources/using-usergrid/creating-account.txt new file mode 100644 index 0000000000..90fe0e15c9 --- /dev/null +++ b/content/docs/_sources/using-usergrid/creating-account.txt @@ -0,0 +1,21 @@ +# Creating a Usergrid Account +To get started using the Usergrid, you'll need an Usergrid account. (Before reading this, you should already be familiar with what Usergrid can do to support your apps. If you're still curious about that, you might want to read Usergrid features first.) + +With an account, you get the following useful things: + +* A sandbox application you can try things with (we automatically create one for you with your new account). The sandbox is a partitioned area of the data store where you can add example data and try out API calls. The sandbox isn't secure, but it's handy to play in. For more about the sandbox, see [Using Your Application Sandbox](../getting-started/using-a-sandbox-app.html). +* The ability to create more applications (in addition to the sandbox). You can (and should!) make these as secure as you need to. These are the applications that you'll have behind the apps you make available to your users. +* Access to the Admin Portal. In the portal, you can do the following: + * Create and manage applications. + * Manage your app's users, including access levels. + * Manage the data in your app. + * Manage app features, including push notifications, activities, analytics, and so on. + * Try out API calls with a shell command window. + * To create an Usergrid account and see a very short tutorial to get started with, go to the get started page of the Portal. + +## Next steps +Ready to learn and do more? + +* Install an SDK that will be most useful for your application environment. For more about Usergrid's SDKs, see [SDKs](../sdks/tbd.html). +* Review Usergrid features for information on concepts and features. +* Consult the API Reference for usage details. \ No newline at end of file diff --git a/content/docs/_sources/using-usergrid/using-a-sandbox-app.txt b/content/docs/_sources/using-usergrid/using-a-sandbox-app.txt new file mode 100644 index 0000000000..75c296f5c8 --- /dev/null +++ b/content/docs/_sources/using-usergrid/using-a-sandbox-app.txt @@ -0,0 +1,39 @@ +# Using a Sandbox Application + +## What is the sandbox application? + +When you create a new Usergrid account (see [Creating an Usergrid Account](creating-account.html)) to use services for developers, Usergrid creates a new application for you on its servers. With the new application, called "sandbox," you can add your own example data and try out API calls that do things with the data. Be sure to see Using the API for suggestions. + +## Is the sandbox secure? + +To keep things simple and make it easier for you to try things out, the sandbox application has all authentication disabled. That way, it doesn’t require an access token for application-level calls to the API. Permissions are so open on the sandbox application because its "guest" role offers full permissions for all access paths -- that is, GET, POST, PUT, and DELETE for /**. Learn more about roles and permissions in Managing access by defining permission rules. + + +

Warning

+

Never use a sandbox app for production. +Keep in mind that the lack of authentication means that a sandbox application is not secure enough for important or sensitive data. A sandbox is just for experimentation while you learn how the services work, and should never be used for a production application. As with other Usergrid applications you create, a sandbox application is an area of the data store where you can put your own data. You can create as many other applications as you like, including more sandbox applications. When it comes to production (secured) applications, a good rule of thumb is to create one application for each mobile app you develop. +

+
+ +## Creating a New Sandbox Application + +You may want to create (or re-create) a sandbox application. For example, you may want to create a sandbox application for another organization or you may want to create another application for testing purposes. + + +

Warning

+Guest Role should never be given full permissions. +Giving the guest role full permissions should be used only for testing and should not be used in production. Before you make your app “live”, you should remove the guest permissions for /**. +

+ +Use the following steps to create a sandbox app: + +1. Create a new application using the admin portal. You can name the application whatever you like (including "sandbox"). +2. Set full access permissions for the guest role, as follows: + 1. In the admin portal, click Users, then click Roles. + 2. On the Roles page, in the list of roles, click Guest. + 3. For the Guest role, under Permissions, click Add Permission. + 4. In the New Permission dialog, enter the following in the Path box: ``/**`` + 5. Select the following check boxes: get, post, put, and delete. + 6. Click the Add button. + 7. If there are other permissions listed, delete them. + diff --git a/content/docs/_sources/using-usergrid/using-the-api.txt b/content/docs/_sources/using-usergrid/using-the-api.txt new file mode 100644 index 0000000000..d85f86a97c --- /dev/null +++ b/content/docs/_sources/using-usergrid/using-the-api.txt @@ -0,0 +1,150 @@ +# Using the API +Usergrid uses a pure REST (Representational State Transfer) API built as a collection of resources. Resource locations are described by paths that are related intrinsically to collections and entities in collections. + +This section gives several examples of how to construct API requests. To focus on what's important, the examples use an abbreviated path that starts after the application UUID, or application name. For example, instead of giving a fully qualified path name as in: + + https://api.usergrid.com/your-org/your-app/users + +the example simply lists this: + + /users + +## Supported HTTP methods +When building a REST API, the challenge is to represent the data and the action upon the data as a path to a resource that can be created, retrieved, updated, or deleted. The HTTP methods POST, GET, PUT, and DELETE correspond to the actions that are applied to resources. + +## Base URL +The base url for all requests made to Usergrid depends on where you have Usergrid installed. If you are using Apigee's trial Usergrid service, the base URL is ``https://api.usergrid.com.`` + +## Request construction +Usergrid interprets the URL resource path as a list of names, UUIDs, or queries. The basic path format is: + + https://api.usergrid.com//// + +Note: You cannot mix UUIDs and names in the URL resource path. For example, the following is incorrect: + + https://api.usergrid.com/your-org/62de5d97-d28c-11e1-8d5c-12313b01d5c1/users/john.doe + +## Accessing collections +To access all entities in a collection, specify the path as follows: + + /users + +Such a request retrieves the first 10 entities in the collection /users sorted by their entity UUID. + +## Accessing entities +To access an entity in a collection, specify the path as follows: + + // + +where ```` is the collection name, and is the entity’s uuid or name. + +To access a user in the users collection, specify the path as follows: + + /users/ + +where ```` is the user’s uuid, username, or email address. + +For example, the following request retrieves the entity named dino from the dogs collection: + + /dogs/dino + +## Issuing queries +You can issue a query in an API request that retrieves items from a collection. Here is the typical format for queries: + + /?ql= + +where is a query in the query language. + +For example, this request retrieves users whose Facebook first name is john: + + /users?ql=select * where facebook.first_name ='john' + +For further information about queries, see [Querying your Data](../data-queries/querying-your-data.html) + +## Authentication (OAuth) +Usergrid implements the OAuth 2.0 standard for authenticating users, clients and API requests. + +Generally, you will generate a token for every user of your app by providing the user's username and password. The token can then be sent with all API requests to ensure each user is only able to access and modify the resources you have granted them rights to. + +Note that by default access tokens are not needed to make requests to the default sandbox application in an organization. + +For more information on generating and using access tokens, see Authenticating users and application clients and Authenticating API requests. + +## Response format +All API methods return a response object that typically contains an array of entities: + + { + "entities" : [ + ... + ] + } + +Not everything can be included inside the entity, and some of the data that gets associated with specific entities isn't part of their persistent representation. This is metadata, and it can be part of the response as well as associated with a specific entity. Metadata is just an arbitrary key/value JSON structure. + +For example: + + { + "entities" : { + { + "name" : "ed", + "metadata" : { + "collections" : ["activities", "groups", "followers"] + } + } + }, + "metadata" : { + "foo" : ["bar", "baz"] + } + } + +For example, here is the response to a basic GET for a user entity: + + { + "action" : "get", + "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0", + "params" : { }, + "path" : "/users", + "uri" : "https://api.usergrid.com/your-org/your-app/users", + "entities" : [ { + "uuid" : "503f17da-ec39-11e3-a0dd-a554b7fbd57a", + "type" : "user", + "created" : 1401921665485, + "modified" : 1401921665485, + "username" : "someUser", + "email" : "someUser@yourdomain.com", + "activated" : true, + "picture" : "http://www.gravatar.com/avatar/dc5d478e9c029853fbd025bed0dc51f8", + "metadata" : { + "path" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a", + "sets" : { + "rolenames" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/roles", + "permissions" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/permissions" + }, + "collections" : { + "activities" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/activities", + "devices" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/devices", + "feed" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/feed", + "groups" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/groups", + "roles" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/roles", + "following" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/following", + "followers" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/followers" + } + } + } ], + "timestamp" : 1401921673597, + "duration" : 12, + "organization" : "your-org", + "applicationName" : "your-app" + } + +## SDKs +To make the integration of Usergrid features into your application code quicker and easier, Usegrid offers SDKs in a variety of languages. The SDKs contain language-specific methods that allow you to issue API requests from your application code in your preferred language. SDKs are available for the following languages: + +* iOS +* Android +* JavaScript/HTML5 +* Node.js +* Ruby +* .NET + +For more information, see SDKs. \ No newline at end of file diff --git a/content/docs/_static/ajax-loader.gif b/content/docs/_static/ajax-loader.gif new file mode 100644 index 0000000000..61faf8cab2 Binary files /dev/null and b/content/docs/_static/ajax-loader.gif differ diff --git a/content/docs/_static/basic.css b/content/docs/_static/basic.css new file mode 100644 index 0000000000..9fa77d886d --- /dev/null +++ b/content/docs/_static/basic.css @@ -0,0 +1,599 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox input[type="text"] { + width: 170px; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + width: 30px; +} + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- general body styles --------------------------------------------------- */ + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.field-list ul { + padding-left: 1em; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.field-list td, table.field-list th { + border: 0 !important; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text { +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +div.code-block-caption { + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +div.code-block-caption + div > div.highlight > pre { + margin-top: 0; +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + padding: 1em 1em 0; +} + +div.literal-block-wrapper div.highlight { + margin: 0; +} + +code.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +code.descclassname { + background-color: transparent; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/content/docs/_static/comment-bright.png b/content/docs/_static/comment-bright.png new file mode 100644 index 0000000000..551517b8c8 Binary files /dev/null and b/content/docs/_static/comment-bright.png differ diff --git a/content/docs/_static/comment-close.png b/content/docs/_static/comment-close.png new file mode 100644 index 0000000000..09b54be46d Binary files /dev/null and b/content/docs/_static/comment-close.png differ diff --git a/content/docs/_static/comment.png b/content/docs/_static/comment.png new file mode 100644 index 0000000000..92feb52b88 Binary files /dev/null and b/content/docs/_static/comment.png differ diff --git a/content/docs/_static/css/badge_only.css b/content/docs/_static/css/badge_only.css new file mode 100644 index 0000000000..5f8b7208f2 --- /dev/null +++ b/content/docs/_static/css/badge_only.css @@ -0,0 +1,4 @@ +.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}} +/*# sourceMappingURL=badge_only.css.map */ + + diff --git a/content/docs/_static/css/badge_only.css.map b/content/docs/_static/css/badge_only.css.map new file mode 100644 index 0000000000..b09cc628bf --- /dev/null +++ b/content/docs/_static/css/badge_only.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "CAyDA,SAAY,EACV,qBAAsB,EAAE,UAAW,EAqDrC,QAAS,EARP,IAAK,EAAE,AAAC,EACR,+BAAS,EAEP,MAAO,EAAE,IAAK,EACd,MAAO,EAAE,CAAE,EACb,cAAO,EACL,IAAK,EAAE,GAAI,EC1Gb,SAkBC,EAjBC,UAAW,ECFJ,UAAW,EDGlB,UAAW,EAHqC,KAAM,EAItD,SAAU,EAJsD,KAAM,EAapE,EAAG,EAAE,qCAAwB,EAC7B,EAAG,EAAE,0PAAyE,ECZpF,SAAU,EACR,MAAO,EAAE,WAAY,EACrB,UAAW,EAAE,UAAW,EACxB,SAAU,EAAE,KAAM,EAClB,UAAW,EAAE,KAAM,EACnB,UAAW,EAAE,AAAC,EACd,cAAe,EAAE,MAAO,EAG1B,IAAK,EACH,MAAO,EAAE,WAAY,EACrB,cAAe,EAAE,MAAO,EAIxB,KAAG,EACD,MAAO,EAAE,WAAY,EACvB,sCAAiB,EAGf,IAAK,EAAE,MAAY,EAEvB,KAAM,EACJ,cAAe,EAAE,GAAI,EACrB,UAAW,EAAE,EAAG,EAChB,UAAW,EAAE,KAAM,EAEjB,YAAG,EACD,IAAK,EAAE,IAAI,EACb,oDAAiB,EAGf,aAAc,EAAE,OAAQ,EAG9B,cAAe,EACb,MAAO,EAAE,EAAO,EAElB,gBAAiB,EACf,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,sBAAuB,EACrB,MAAO,EAAE,EAAO,EAElB,kBAAmB,EACjB,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,sBAAuB,EACrB,MAAO,EAAE,EAAO,EAElB,qBAAsB,EACpB,MAAO,EAAE,EAAO,EAElB,uBAAwB,EACtB,MAAO,EAAE,EAAO,ECnElB,YAAa,EACX,OAAQ,EAAE,IAAK,EACf,KAAM,EAAE,AAAC,EACT,GAAI,EAAE,AAAC,EACP,IAAK,EC6E+B,IAAK,ED5EzC,IAAK,ECE+B,MAAyB,EDD7D,SAAU,EAAE,MAAkC,EAC9C,SAAU,EAAE,iBAAiC,EAC7C,UAAW,EEAyB,sDAAM,EFC1C,MAAO,EC+E6B,EAAG,ED9EvC,cAAC,EACC,IAAK,ECqE6B,MAAW,EDpE7C,cAAe,EAAE,GAAI,EACvB,6BAAgB,EACd,MAAO,EAAE,GAAI,EACf,iCAAoB,EAClB,MAAO,EAAE,GAAqB,EAC9B,eAAgB,EAAE,MAAkC,EACpD,MAAO,EAAE,IAAK,EACd,SAAU,EAAE,IAAK,EACjB,QAAS,EAAE,EAAG,EACd,KAAM,EAAE,MAAO,EACf,IAAK,ECiD6B,MAAM,EJgC1C,IAAK,EAAE,AAAC,EACR,iFAAS,EAEP,MAAO,EAAE,IAAK,EACd,MAAO,EAAE,CAAE,EACb,uCAAO,EACL,IAAK,EAAE,GAAI,EGrFX,qCAAG,EACD,IAAK,EClB2B,MAAyB,EDmB3D,0CAAQ,EACN,IAAK,EAAE,GAAI,EACb,4CAAU,EACR,IAAK,EAAE,GAAI,EACb,iDAAiB,EACf,eAAgB,ECQgB,MAAI,EDPpC,IAAK,EC0B2B,GAAM,EDzBxC,wDAAwB,EACtB,eAAgB,ECXgB,MAAO,EDYvC,IAAK,ECzB2B,GAAI,ED0BxC,yCAA8B,EAC5B,MAAO,EAAE,IAAK,EAChB,gCAAmB,EACjB,QAAS,EAAE,EAAG,EACd,MAAO,EAAE,GAAqB,EAC9B,IAAK,ECE6B,GAAwB,EDD1D,MAAO,EAAE,GAAI,EACb,mCAAE,EACA,MAAO,EAAE,IAAK,EACd,KAAM,EAAE,EAAG,EACX,KAAM,EAAE,AAAC,EACT,KAAM,EAAE,KAAM,EACd,MAAO,EAAE,AAAC,EACV,SAAU,EAAE,gBAA6C,EAC3D,mCAAE,EACA,MAAO,EAAE,WAAY,EACrB,KAAM,EAAE,AAAC,EACT,qCAAC,EACC,MAAO,EAAE,WAAY,EACrB,MAAO,EAAE,EAAqB,EAC9B,IAAK,ECjDyB,MAAyB,EDkD7D,sBAAW,EACT,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI,EACZ,IAAK,EAAE,GAAI,EACX,GAAI,EAAE,GAAI,EACV,KAAM,EAAE,GAAI,EACZ,QAAS,ECkByB,IAAK,EDjBvC,iCAAU,EACR,IAAK,EAAE,GAAI,EACb,+BAAQ,EACN,IAAK,EAAE,GAAI,EACb,oDAA+B,EAC7B,SAAU,EAAE,IAAK,EACjB,6DAAQ,EACN,IAAK,EAAE,GAAI,EACb,+DAAU,EACR,IAAK,EAAE,GAAI,EACf,2CAAoB,EAClB,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI,EACZ,UAAW,EAAE,GAAI,EACjB,MAAO,EAAE,IAAuB,EAChC,MAAO,EAAE,IAAK,EACd,SAAU,EAAE,KAAM,EGhDpB,mCAAsB,EHmDxB,YAAa,EACX,IAAK,EAAE,EAAG,EACV,MAAO,EAAE,GAAI,EACb,kBAAO,EACL,MAAO,EAAE,IAAK,EAClB,EAAG,EACD,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI", +"sources": ["../../../bower_components/wyrm/sass/wyrm_core/_mixin.sass","../../../bower_components/bourbon/dist/css3/_font-face.scss","../../../sass/_theme_badge_fa.sass","../../../sass/_theme_badge.sass","../../../bower_components/wyrm/sass/wyrm_core/_wy_variables.sass","../../../sass/_theme_variables.sass","../../../bower_components/neat/app/assets/stylesheets/grid/_media.scss"], +"names": [], +"file": "badge_only.css" +} diff --git a/content/docs/_static/css/theme.css b/content/docs/_static/css/theme.css new file mode 100644 index 0000000000..b0b1c33201 --- /dev/null +++ b/content/docs/_static/css/theme.css @@ -0,0 +1,5384 @@ +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { + display: block +} + +audio, canvas, video { + display: inline-block; + *display: inline; + *zoom: 1 +} + +audio:not([controls]) { + display: none +} + +[hidden] { + display: none +} + +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100% +} + +body { + margin: 0 +} + +a:hover, a:active { + outline: 0 +} + +abbr[title] { + border-bottom: 1px dotted +} + +b, strong { + font-weight: bold +} + +blockquote { + margin: 0 +} + +dfn { + font-style: italic +} + +ins { + background: #ff9; + color: #000; + text-decoration: none +} + +mark { + background: #ff0; + color: #000; + font-style: italic; + font-weight: bold +} + +pre, code, .rst-content tt, .rst-content code, kbd, samp { + font-family: monospace, serif; + _font-family: "courier new", monospace; + font-size: 1em +} + +pre { + white-space: pre +} + +q { + quotes: none +} + +q:before, q:after { + content: ""; + content: none +} + +small { + font-size: 85% +} + +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline +} + +sup { + top: -0.5em +} + +sub { + bottom: -0.25em +} + +ul, ol, dl { + margin: 0; + padding: 0; + list-style: none; + list-style-image: none +} + +li { + list-style: none +} + +dd { + margin: 0 +} + +img { + border: 0; + -ms-interpolation-mode: bicubic; + vertical-align: middle; + max-width: 100% +} + +svg:not(:root) { + overflow: hidden +} + +figure { + margin: 0 +} + +form { + margin: 0 +} + +fieldset { + border: 0; + margin: 0; + padding: 0 +} + +label { + cursor: pointer +} + +legend { + border: 0; + *margin-left: -7px; + padding: 0; + white-space: normal +} + +button, input, select, textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle +} + +button, input { + line-height: normal +} + +button, input[type="button"], input[type="reset"], input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; + *overflow: visible +} + +button[disabled], input[disabled] { + cursor: default +} + +input[type="checkbox"], input[type="radio"] { + box-sizing: border-box; + padding: 0; + *width: 13px; + *height: 13px +} + +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box +} + +input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none +} + +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0 +} + +textarea { + overflow: auto; + vertical-align: top; + resize: vertical +} + +table { + border-collapse: collapse; + border-spacing: 0 +} + +td { + vertical-align: top +} + +.chromeframe { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0 +} + +.ir { + display: block; + border: 0; + text-indent: -999em; + overflow: hidden; + background-color: transparent; + background-repeat: no-repeat; + text-align: left; + direction: ltr; + *line-height: 0 +} + +.ir br { + display: none +} + +.hidden { + display: none !important; + visibility: hidden +} + +.visuallyhidden { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px +} + +.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto +} + +.invisible { + visibility: hidden +} + +.relative { + position: relative +} + +big, small { + font-size: 100% +} + +@media print { + html, body, section { + background: none !important + } + + * { + box-shadow: none !important; + text-shadow: none !important; + filter: none !important; + -ms-filter: none !important + } + + a, a:visited { + text-decoration: underline + } + + .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { + content: "" + } + + pre, blockquote { + page-break-inside: avoid + } + + thead { + display: table-header-group + } + + tr, img { + page-break-inside: avoid + } + + img { + max-width: 100% !important + } + + @page { + margin: 0.5cm + } + + p, h2, .rst-content .toctree-wrapper p.caption, h3 { + orphans: 3; + widows: 3 + } + + h2, .rst-content .toctree-wrapper p.caption, h3 { + page-break-after: avoid + } +} + +.fa:before, .wy-menu-vertical li span.toctree-expand:before, .wy-menu-vertical li.on a span.toctree-expand:before, .wy-menu-vertical li.current > a span.toctree-expand:before, .rst-content .admonition-title:before, .rst-content h1 .headerlink:before, .rst-content h2 .headerlink:before, .rst-content h3 .headerlink:before, .rst-content h4 .headerlink:before, .rst-content h5 .headerlink:before, .rst-content h6 .headerlink:before, .rst-content dl dt .headerlink:before, .rst-content p.caption .headerlink:before, .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before, .icon:before, .wy-dropdown .caret:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .wy-alert, .rst-content .note, .rst-content .attention, .rst-content .caution, .rst-content .danger, .rst-content .error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .warning, .rst-content .seealso, .rst-content .admonition-todo, .btn, input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"], select, textarea, .wy-menu-vertical li.on a, .wy-menu-vertical li.current > a, .wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a, .wy-nav-top a { + -webkit-font-smoothing: antialiased +} + +.clearfix { + *zoom: 1 +} + +.clearfix:before, .clearfix:after { + display: table; + content: "" +} + +.clearfix:after { + clear: both +} + +/*! + * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +@font-face { + font-family: 'FontAwesome'; + src: url("../fonts/fontawesome-webfont.eot?v=4.2.0"); + src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0") format("embedded-opentype"), url("../fonts/fontawesome-webfont.woff?v=4.2.0") format("woff"), url("../fonts/fontawesome-webfont.ttf?v=4.2.0") format("truetype"), url("../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular") format("svg"); + font-weight: normal; + font-style: normal +} + +.fa, .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand, .rst-content .admonition-title, .rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .rst-content p.caption .headerlink, .rst-content tt.download span:first-child, .rst-content code.download span:first-child, .icon { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale +} + +.fa-lg { + font-size: 1.33333em; + line-height: 0.75em; + vertical-align: -15% +} + +.fa-2x { + font-size: 2em +} + +.fa-3x { + font-size: 3em +} + +.fa-4x { + font-size: 4em +} + +.fa-5x { + font-size: 5em +} + +.fa-fw { + width: 1.28571em; + text-align: center +} + +.fa-ul { + padding-left: 0; + margin-left: 2.14286em; + list-style-type: none +} + +.fa-ul > li { + position: relative +} + +.fa-li { + position: absolute; + left: -2.14286em; + width: 2.14286em; + top: 0.14286em; + text-align: center +} + +.fa-li.fa-lg { + left: -1.85714em +} + +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eee; + border-radius: .1em +} + +.pull-right { + float: right +} + +.pull-left { + float: left +} + +.fa.pull-left, .wy-menu-vertical li span.pull-left.toctree-expand, .wy-menu-vertical li.on a span.pull-left.toctree-expand, .wy-menu-vertical li.current > a span.pull-left.toctree-expand, .rst-content .pull-left.admonition-title, .rst-content h1 .pull-left.headerlink, .rst-content h2 .pull-left.headerlink, .rst-content h3 .pull-left.headerlink, .rst-content h4 .pull-left.headerlink, .rst-content h5 .pull-left.headerlink, .rst-content h6 .pull-left.headerlink, .rst-content dl dt .pull-left.headerlink, .rst-content p.caption .pull-left.headerlink, .rst-content tt.download span.pull-left:first-child, .rst-content code.download span.pull-left:first-child, .pull-left.icon { + margin-right: .3em +} + +.fa.pull-right, .wy-menu-vertical li span.pull-right.toctree-expand, .wy-menu-vertical li.on a span.pull-right.toctree-expand, .wy-menu-vertical li.current > a span.pull-right.toctree-expand, .rst-content .pull-right.admonition-title, .rst-content h1 .pull-right.headerlink, .rst-content h2 .pull-right.headerlink, .rst-content h3 .pull-right.headerlink, .rst-content h4 .pull-right.headerlink, .rst-content h5 .pull-right.headerlink, .rst-content h6 .pull-right.headerlink, .rst-content dl dt .pull-right.headerlink, .rst-content p.caption .pull-right.headerlink, .rst-content tt.download span.pull-right:first-child, .rst-content code.download span.pull-right:first-child, .pull-right.icon { + margin-left: .3em +} + +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear +} + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg) + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg) + } +} + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg) + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg) + } +} + +.fa-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg) +} + +.fa-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg) +} + +.fa-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg) +} + +.fa-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0); + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1) +} + +.fa-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1) +} + +:root .fa-rotate-90, :root .fa-rotate-180, :root .fa-rotate-270, :root .fa-flip-horizontal, :root .fa-flip-vertical { + filter: none +} + +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle +} + +.fa-stack-1x, .fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center +} + +.fa-stack-1x { + line-height: inherit +} + +.fa-stack-2x { + font-size: 2em +} + +.fa-inverse { + color: #fff +} + +.fa-glass:before { + content: "" +} + +.fa-music:before { + content: "" +} + +.fa-search:before, .icon-search:before { + content: "" +} + +.fa-envelope-o:before { + content: "" +} + +.fa-heart:before { + content: "" +} + +.fa-star:before { + content: "" +} + +.fa-star-o:before { + content: "" +} + +.fa-user:before { + content: "" +} + +.fa-film:before { + content: "" +} + +.fa-th-large:before { + content: "" +} + +.fa-th:before { + content: "" +} + +.fa-th-list:before { + content: "" +} + +.fa-check:before { + content: "" +} + +.fa-remove:before, .fa-close:before, .fa-times:before { + content: "" +} + +.fa-search-plus:before { + content: "" +} + +.fa-search-minus:before { + content: "" +} + +.fa-power-off:before { + content: "" +} + +.fa-signal:before { + content: "" +} + +.fa-gear:before, .fa-cog:before { + content: "" +} + +.fa-trash-o:before { + content: "" +} + +.fa-home:before, .icon-home:before { + content: "" +} + +.fa-file-o:before { + content: "" +} + +.fa-clock-o:before { + content: "" +} + +.fa-road:before { + content: "" +} + +.fa-download:before, .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before { + content: "" +} + +.fa-arrow-circle-o-down:before { + content: "" +} + +.fa-arrow-circle-o-up:before { + content: "" +} + +.fa-inbox:before { + content: "" +} + +.fa-play-circle-o:before { + content: "" +} + +.fa-rotate-right:before, .fa-repeat:before { + content: "" +} + +.fa-refresh:before { + content: "" +} + +.fa-list-alt:before { + content: "" +} + +.fa-lock:before { + content: "" +} + +.fa-flag:before { + content: "" +} + +.fa-headphones:before { + content: "" +} + +.fa-volume-off:before { + content: "" +} + +.fa-volume-down:before { + content: "" +} + +.fa-volume-up:before { + content: "" +} + +.fa-qrcode:before { + content: "" +} + +.fa-barcode:before { + content: "" +} + +.fa-tag:before { + content: "" +} + +.fa-tags:before { + content: "" +} + +.fa-book:before, .icon-book:before { + content: "" +} + +.fa-bookmark:before { + content: "" +} + +.fa-print:before { + content: "" +} + +.fa-camera:before { + content: "" +} + +.fa-font:before { + content: "" +} + +.fa-bold:before { + content: "" +} + +.fa-italic:before { + content: "" +} + +.fa-text-height:before { + content: "" +} + +.fa-text-width:before { + content: "" +} + +.fa-align-left:before { + content: "" +} + +.fa-align-center:before { + content: "" +} + +.fa-align-right:before { + content: "" +} + +.fa-align-justify:before { + content: "" +} + +.fa-list:before { + content: "" +} + +.fa-dedent:before, .fa-outdent:before { + content: "" +} + +.fa-indent:before { + content: "" +} + +.fa-video-camera:before { + content: "" +} + +.fa-photo:before, .fa-image:before, .fa-picture-o:before { + content: "" +} + +.fa-pencil:before { + content: "" +} + +.fa-map-marker:before { + content: "" +} + +.fa-adjust:before { + content: "" +} + +.fa-tint:before { + content: "" +} + +.fa-edit:before, .fa-pencil-square-o:before { + content: "" +} + +.fa-share-square-o:before { + content: "" +} + +.fa-check-square-o:before { + content: "" +} + +.fa-arrows:before { + content: "" +} + +.fa-step-backward:before { + content: "" +} + +.fa-fast-backward:before { + content: "" +} + +.fa-backward:before { + content: "" +} + +.fa-play:before { + content: "" +} + +.fa-pause:before { + content: "" +} + +.fa-stop:before { + content: "" +} + +.fa-forward:before { + content: "" +} + +.fa-fast-forward:before { + content: "" +} + +.fa-step-forward:before { + content: "" +} + +.fa-eject:before { + content: "" +} + +.fa-chevron-left:before { + content: "" +} + +.fa-chevron-right:before { + content: "" +} + +.fa-plus-circle:before { + content: "" +} + +.fa-minus-circle:before { + content: "" +} + +.fa-times-circle:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before { + content: "" +} + +.fa-check-circle:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before { + content: "" +} + +.fa-question-circle:before { + content: "" +} + +.fa-info-circle:before { + content: "" +} + +.fa-crosshairs:before { + content: "" +} + +.fa-times-circle-o:before { + content: "" +} + +.fa-check-circle-o:before { + content: "" +} + +.fa-ban:before { + content: "" +} + +.fa-arrow-left:before { + content: "" +} + +.fa-arrow-right:before { + content: "" +} + +.fa-arrow-up:before { + content: "" +} + +.fa-arrow-down:before { + content: "" +} + +.fa-mail-forward:before, .fa-share:before { + content: "" +} + +.fa-expand:before { + content: "" +} + +.fa-compress:before { + content: "" +} + +.fa-plus:before { + content: "" +} + +.fa-minus:before { + content: "" +} + +.fa-asterisk:before { + content: "" +} + +.fa-exclamation-circle:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before, .rst-content .admonition-title:before { + content: "" +} + +.fa-gift:before { + content: "" +} + +.fa-leaf:before { + content: "" +} + +.fa-fire:before, .icon-fire:before { + content: "" +} + +.fa-eye:before { + content: "" +} + +.fa-eye-slash:before { + content: "" +} + +.fa-warning:before, .fa-exclamation-triangle:before { + content: "" +} + +.fa-plane:before { + content: "" +} + +.fa-calendar:before { + content: "" +} + +.fa-random:before { + content: "" +} + +.fa-comment:before { + content: "" +} + +.fa-magnet:before { + content: "" +} + +.fa-chevron-up:before { + content: "" +} + +.fa-chevron-down:before { + content: "" +} + +.fa-retweet:before { + content: "" +} + +.fa-shopping-cart:before { + content: "" +} + +.fa-folder:before { + content: "" +} + +.fa-folder-open:before { + content: "" +} + +.fa-arrows-v:before { + content: "" +} + +.fa-arrows-h:before { + content: "" +} + +.fa-bar-chart-o:before, .fa-bar-chart:before { + content: "" +} + +.fa-twitter-square:before { + content: "" +} + +.fa-facebook-square:before { + content: "" +} + +.fa-camera-retro:before { + content: "" +} + +.fa-key:before { + content: "" +} + +.fa-gears:before, .fa-cogs:before { + content: "" +} + +.fa-comments:before { + content: "" +} + +.fa-thumbs-o-up:before { + content: "" +} + +.fa-thumbs-o-down:before { + content: "" +} + +.fa-star-half:before { + content: "" +} + +.fa-heart-o:before { + content: "" +} + +.fa-sign-out:before { + content: "" +} + +.fa-linkedin-square:before { + content: "" +} + +.fa-thumb-tack:before { + content: "" +} + +.fa-external-link:before { + content: "" +} + +.fa-sign-in:before { + content: "" +} + +.fa-trophy:before { + content: "" +} + +.fa-github-square:before { + content: "" +} + +.fa-upload:before { + content: "" +} + +.fa-lemon-o:before { + content: "" +} + +.fa-phone:before { + content: "" +} + +.fa-square-o:before { + content: "" +} + +.fa-bookmark-o:before { + content: "" +} + +.fa-phone-square:before { + content: "" +} + +.fa-twitter:before { + content: "" +} + +.fa-facebook:before { + content: "" +} + +.fa-github:before, .icon-github:before { + content: "" +} + +.fa-unlock:before { + content: "" +} + +.fa-credit-card:before { + content: "" +} + +.fa-rss:before { + content: "" +} + +.fa-hdd-o:before { + content: "" +} + +.fa-bullhorn:before { + content: "" +} + +.fa-bell:before { + content: "" +} + +.fa-certificate:before { + content: "" +} + +.fa-hand-o-right:before { + content: "" +} + +.fa-hand-o-left:before { + content: "" +} + +.fa-hand-o-up:before { + content: "" +} + +.fa-hand-o-down:before { + content: "" +} + +.fa-arrow-circle-left:before, .icon-circle-arrow-left:before { + content: "" +} + +.fa-arrow-circle-right:before, .icon-circle-arrow-right:before { + content: "" +} + +.fa-arrow-circle-up:before { + content: "" +} + +.fa-arrow-circle-down:before { + content: "" +} + +.fa-globe:before { + content: "" +} + +.fa-wrench:before { + content: "" +} + +.fa-tasks:before { + content: "" +} + +.fa-filter:before { + content: "" +} + +.fa-briefcase:before { + content: "" +} + +.fa-arrows-alt:before { + content: "" +} + +.fa-group:before, .fa-users:before { + content: "" +} + +.fa-chain:before, .fa-link:before, .icon-link:before { + content: "" +} + +.fa-cloud:before { + content: "" +} + +.fa-flask:before { + content: "" +} + +.fa-cut:before, .fa-scissors:before { + content: "" +} + +.fa-copy:before, .fa-files-o:before { + content: "" +} + +.fa-paperclip:before { + content: "" +} + +.fa-save:before, .fa-floppy-o:before { + content: "" +} + +.fa-square:before { + content: "" +} + +.fa-navicon:before, .fa-reorder:before, .fa-bars:before { + content: "" +} + +.fa-list-ul:before { + content: "" +} + +.fa-list-ol:before { + content: "" +} + +.fa-strikethrough:before { + content: "" +} + +.fa-underline:before { + content: "" +} + +.fa-table:before { + content: "" +} + +.fa-magic:before { + content: "" +} + +.fa-truck:before { + content: "" +} + +.fa-pinterest:before { + content: "" +} + +.fa-pinterest-square:before { + content: "" +} + +.fa-google-plus-square:before { + content: "" +} + +.fa-google-plus:before { + content: "" +} + +.fa-money:before { + content: "" +} + +.fa-caret-down:before, .wy-dropdown .caret:before, .icon-caret-down:before { + content: "" +} + +.fa-caret-up:before { + content: "" +} + +.fa-caret-left:before { + content: "" +} + +.fa-caret-right:before { + content: "" +} + +.fa-columns:before { + content: "" +} + +.fa-unsorted:before, .fa-sort:before { + content: "" +} + +.fa-sort-down:before, .fa-sort-desc:before { + content: "" +} + +.fa-sort-up:before, .fa-sort-asc:before { + content: "" +} + +.fa-envelope:before { + content: "" +} + +.fa-linkedin:before { + content: "" +} + +.fa-rotate-left:before, .fa-undo:before { + content: "" +} + +.fa-legal:before, .fa-gavel:before { + content: "" +} + +.fa-dashboard:before, .fa-tachometer:before { + content: "" +} + +.fa-comment-o:before { + content: "" +} + +.fa-comments-o:before { + content: "" +} + +.fa-flash:before, .fa-bolt:before { + content: "" +} + +.fa-sitemap:before { + content: "" +} + +.fa-umbrella:before { + content: "" +} + +.fa-paste:before, .fa-clipboard:before { + content: "" +} + +.fa-lightbulb-o:before { + content: "" +} + +.fa-exchange:before { + content: "" +} + +.fa-cloud-download:before { + content: "" +} + +.fa-cloud-upload:before { + content: "" +} + +.fa-user-md:before { + content: "" +} + +.fa-stethoscope:before { + content: "" +} + +.fa-suitcase:before { + content: "" +} + +.fa-bell-o:before { + content: "" +} + +.fa-coffee:before { + content: "" +} + +.fa-cutlery:before { + content: "" +} + +.fa-file-text-o:before { + content: "" +} + +.fa-building-o:before { + content: "" +} + +.fa-hospital-o:before { + content: "" +} + +.fa-ambulance:before { + content: "" +} + +.fa-medkit:before { + content: "" +} + +.fa-fighter-jet:before { + content: "" +} + +.fa-beer:before { + content: "" +} + +.fa-h-square:before { + content: "" +} + +.fa-plus-square:before { + content: "" +} + +.fa-angle-double-left:before { + content: "" +} + +.fa-angle-double-right:before { + content: "" +} + +.fa-angle-double-up:before { + content: "" +} + +.fa-angle-double-down:before { + content: "" +} + +.fa-angle-left:before { + content: "" +} + +.fa-angle-right:before { + content: "" +} + +.fa-angle-up:before { + content: "" +} + +.fa-angle-down:before { + content: "" +} + +.fa-desktop:before { + content: "" +} + +.fa-laptop:before { + content: "" +} + +.fa-tablet:before { + content: "" +} + +.fa-mobile-phone:before, .fa-mobile:before { + content: "" +} + +.fa-circle-o:before { + content: "" +} + +.fa-quote-left:before { + content: "" +} + +.fa-quote-right:before { + content: "" +} + +.fa-spinner:before { + content: "" +} + +.fa-circle:before { + content: "" +} + +.fa-mail-reply:before, .fa-reply:before { + content: "" +} + +.fa-github-alt:before { + content: "" +} + +.fa-folder-o:before { + content: "" +} + +.fa-folder-open-o:before { + content: "" +} + +.fa-smile-o:before { + content: "" +} + +.fa-frown-o:before { + content: "" +} + +.fa-meh-o:before { + content: "" +} + +.fa-gamepad:before { + content: "" +} + +.fa-keyboard-o:before { + content: "" +} + +.fa-flag-o:before { + content: "" +} + +.fa-flag-checkered:before { + content: "" +} + +.fa-terminal:before { + content: "" +} + +.fa-code:before { + content: "" +} + +.fa-mail-reply-all:before, .fa-reply-all:before { + content: "" +} + +.fa-star-half-empty:before, .fa-star-half-full:before, .fa-star-half-o:before { + content: "" +} + +.fa-location-arrow:before { + content: "" +} + +.fa-crop:before { + content: "" +} + +.fa-code-fork:before { + content: "" +} + +.fa-unlink:before, .fa-chain-broken:before { + content: "" +} + +.fa-question:before { + content: "" +} + +.fa-info:before { + content: "" +} + +.fa-exclamation:before { + content: "" +} + +.fa-superscript:before { + content: "" +} + +.fa-subscript:before { + content: "" +} + +.fa-eraser:before { + content: "" +} + +.fa-puzzle-piece:before { + content: "" +} + +.fa-microphone:before { + content: "" +} + +.fa-microphone-slash:before { + content: "" +} + +.fa-shield:before { + content: "" +} + +.fa-calendar-o:before { + content: "" +} + +.fa-fire-extinguisher:before { + content: "" +} + +.fa-rocket:before { + content: "" +} + +.fa-maxcdn:before { + content: "" +} + +.fa-chevron-circle-left:before { + content: "" +} + +.fa-chevron-circle-right:before { + content: "" +} + +.fa-chevron-circle-up:before { + content: "" +} + +.fa-chevron-circle-down:before { + content: "" +} + +.fa-html5:before { + content: "" +} + +.fa-css3:before { + content: "" +} + +.fa-anchor:before { + content: "" +} + +.fa-unlock-alt:before { + content: "" +} + +.fa-bullseye:before { + content: "" +} + +.fa-ellipsis-h:before { + content: "" +} + +.fa-ellipsis-v:before { + content: "" +} + +.fa-rss-square:before { + content: "" +} + +.fa-play-circle:before { + content: "" +} + +.fa-ticket:before { + content: "" +} + +.fa-minus-square:before { + content: "" +} + +.fa-minus-square-o:before, .wy-menu-vertical li.on a span.toctree-expand:before, .wy-menu-vertical li.current > a span.toctree-expand:before { + content: "" +} + +.fa-level-up:before { + content: "" +} + +.fa-level-down:before { + content: "" +} + +.fa-check-square:before { + content: "" +} + +.fa-pencil-square:before { + content: "" +} + +.fa-external-link-square:before { + content: "" +} + +.fa-share-square:before { + content: "" +} + +.fa-compass:before { + content: "" +} + +.fa-toggle-down:before, .fa-caret-square-o-down:before { + content: "" +} + +.fa-toggle-up:before, .fa-caret-square-o-up:before { + content: "" +} + +.fa-toggle-right:before, .fa-caret-square-o-right:before { + content: "" +} + +.fa-euro:before, .fa-eur:before { + content: "" +} + +.fa-gbp:before { + content: "" +} + +.fa-dollar:before, .fa-usd:before { + content: "" +} + +.fa-rupee:before, .fa-inr:before { + content: "" +} + +.fa-cny:before, .fa-rmb:before, .fa-yen:before, .fa-jpy:before { + content: "" +} + +.fa-ruble:before, .fa-rouble:before, .fa-rub:before { + content: "" +} + +.fa-won:before, .fa-krw:before { + content: "" +} + +.fa-bitcoin:before, .fa-btc:before { + content: "" +} + +.fa-file:before { + content: "" +} + +.fa-file-text:before { + content: "" +} + +.fa-sort-alpha-asc:before { + content: "" +} + +.fa-sort-alpha-desc:before { + content: "" +} + +.fa-sort-amount-asc:before { + content: "" +} + +.fa-sort-amount-desc:before { + content: "" +} + +.fa-sort-numeric-asc:before { + content: "" +} + +.fa-sort-numeric-desc:before { + content: "" +} + +.fa-thumbs-up:before { + content: "" +} + +.fa-thumbs-down:before { + content: "" +} + +.fa-youtube-square:before { + content: "" +} + +.fa-youtube:before { + content: "" +} + +.fa-xing:before { + content: "" +} + +.fa-xing-square:before { + content: "" +} + +.fa-youtube-play:before { + content: "" +} + +.fa-dropbox:before { + content: "" +} + +.fa-stack-overflow:before { + content: "" +} + +.fa-instagram:before { + content: "" +} + +.fa-flickr:before { + content: "" +} + +.fa-adn:before { + content: "" +} + +.fa-bitbucket:before, .icon-bitbucket:before { + content: "" +} + +.fa-bitbucket-square:before { + content: "" +} + +.fa-tumblr:before { + content: "" +} + +.fa-tumblr-square:before { + content: "" +} + +.fa-long-arrow-down:before { + content: "" +} + +.fa-long-arrow-up:before { + content: "" +} + +.fa-long-arrow-left:before { + content: "" +} + +.fa-long-arrow-right:before { + content: "" +} + +.fa-apple:before { + content: "" +} + +.fa-windows:before { + content: "" +} + +.fa-android:before { + content: "" +} + +.fa-linux:before { + content: "" +} + +.fa-dribbble:before { + content: "" +} + +.fa-skype:before { + content: "" +} + +.fa-foursquare:before { + content: "" +} + +.fa-trello:before { + content: "" +} + +.fa-female:before { + content: "" +} + +.fa-male:before { + content: "" +} + +.fa-gittip:before { + content: "" +} + +.fa-sun-o:before { + content: "" +} + +.fa-moon-o:before { + content: "" +} + +.fa-archive:before { + content: "" +} + +.fa-bug:before { + content: "" +} + +.fa-vk:before { + content: "" +} + +.fa-weibo:before { + content: "" +} + +.fa-renren:before { + content: "" +} + +.fa-pagelines:before { + content: "" +} + +.fa-stack-exchange:before { + content: "" +} + +.fa-arrow-circle-o-right:before { + content: "" +} + +.fa-arrow-circle-o-left:before { + content: "" +} + +.fa-toggle-left:before, .fa-caret-square-o-left:before { + content: "" +} + +.fa-dot-circle-o:before { + content: "" +} + +.fa-wheelchair:before { + content: "" +} + +.fa-vimeo-square:before { + content: "" +} + +.fa-turkish-lira:before, .fa-try:before { + content: "" +} + +.fa-plus-square-o:before, .wy-menu-vertical li span.toctree-expand:before { + content: "" +} + +.fa-space-shuttle:before { + content: "" +} + +.fa-slack:before { + content: "" +} + +.fa-envelope-square:before { + content: "" +} + +.fa-wordpress:before { + content: "" +} + +.fa-openid:before { + content: "" +} + +.fa-institution:before, .fa-bank:before, .fa-university:before { + content: "" +} + +.fa-mortar-board:before, .fa-graduation-cap:before { + content: "" +} + +.fa-yahoo:before { + content: "" +} + +.fa-google:before { + content: "" +} + +.fa-reddit:before { + content: "" +} + +.fa-reddit-square:before { + content: "" +} + +.fa-stumbleupon-circle:before { + content: "" +} + +.fa-stumbleupon:before { + content: "" +} + +.fa-delicious:before { + content: "" +} + +.fa-digg:before { + content: "" +} + +.fa-pied-piper:before { + content: "" +} + +.fa-pied-piper-alt:before { + content: "" +} + +.fa-drupal:before { + content: "" +} + +.fa-joomla:before { + content: "" +} + +.fa-language:before { + content: "" +} + +.fa-fax:before { + content: "" +} + +.fa-building:before { + content: "" +} + +.fa-child:before { + content: "" +} + +.fa-paw:before { + content: "" +} + +.fa-spoon:before { + content: "" +} + +.fa-cube:before { + content: "" +} + +.fa-cubes:before { + content: "" +} + +.fa-behance:before { + content: "" +} + +.fa-behance-square:before { + content: "" +} + +.fa-steam:before { + content: "" +} + +.fa-steam-square:before { + content: "" +} + +.fa-recycle:before { + content: "" +} + +.fa-automobile:before, .fa-car:before { + content: "" +} + +.fa-cab:before, .fa-taxi:before { + content: "" +} + +.fa-tree:before { + content: "" +} + +.fa-spotify:before { + content: "" +} + +.fa-deviantart:before { + content: "" +} + +.fa-soundcloud:before { + content: "" +} + +.fa-database:before { + content: "" +} + +.fa-file-pdf-o:before { + content: "" +} + +.fa-file-word-o:before { + content: "" +} + +.fa-file-excel-o:before { + content: "" +} + +.fa-file-powerpoint-o:before { + content: "" +} + +.fa-file-photo-o:before, .fa-file-picture-o:before, .fa-file-image-o:before { + content: "" +} + +.fa-file-zip-o:before, .fa-file-archive-o:before { + content: "" +} + +.fa-file-sound-o:before, .fa-file-audio-o:before { + content: "" +} + +.fa-file-movie-o:before, .fa-file-video-o:before { + content: "" +} + +.fa-file-code-o:before { + content: "" +} + +.fa-vine:before { + content: "" +} + +.fa-codepen:before { + content: "" +} + +.fa-jsfiddle:before { + content: "" +} + +.fa-life-bouy:before, .fa-life-buoy:before, .fa-life-saver:before, .fa-support:before, .fa-life-ring:before { + content: "" +} + +.fa-circle-o-notch:before { + content: "" +} + +.fa-ra:before, .fa-rebel:before { + content: "" +} + +.fa-ge:before, .fa-empire:before { + content: "" +} + +.fa-git-square:before { + content: "" +} + +.fa-git:before { + content: "" +} + +.fa-hacker-news:before { + content: "" +} + +.fa-tencent-weibo:before { + content: "" +} + +.fa-qq:before { + content: "" +} + +.fa-wechat:before, .fa-weixin:before { + content: "" +} + +.fa-send:before, .fa-paper-plane:before { + content: "" +} + +.fa-send-o:before, .fa-paper-plane-o:before { + content: "" +} + +.fa-history:before { + content: "" +} + +.fa-circle-thin:before { + content: "" +} + +.fa-header:before { + content: "" +} + +.fa-paragraph:before { + content: "" +} + +.fa-sliders:before { + content: "" +} + +.fa-share-alt:before { + content: "" +} + +.fa-share-alt-square:before { + content: "" +} + +.fa-bomb:before { + content: "" +} + +.fa-soccer-ball-o:before, .fa-futbol-o:before { + content: "" +} + +.fa-tty:before { + content: "" +} + +.fa-binoculars:before { + content: "" +} + +.fa-plug:before { + content: "" +} + +.fa-slideshare:before { + content: "" +} + +.fa-twitch:before { + content: "" +} + +.fa-yelp:before { + content: "" +} + +.fa-newspaper-o:before { + content: "" +} + +.fa-wifi:before { + content: "" +} + +.fa-calculator:before { + content: "" +} + +.fa-paypal:before { + content: "" +} + +.fa-google-wallet:before { + content: "" +} + +.fa-cc-visa:before { + content: "" +} + +.fa-cc-mastercard:before { + content: "" +} + +.fa-cc-discover:before { + content: "" +} + +.fa-cc-amex:before { + content: "" +} + +.fa-cc-paypal:before { + content: "" +} + +.fa-cc-stripe:before { + content: "" +} + +.fa-bell-slash:before { + content: "" +} + +.fa-bell-slash-o:before { + content: "" +} + +.fa-trash:before { + content: "" +} + +.fa-copyright:before { + content: "" +} + +.fa-at:before { + content: "" +} + +.fa-eyedropper:before { + content: "" +} + +.fa-paint-brush:before { + content: "" +} + +.fa-birthday-cake:before { + content: "" +} + +.fa-area-chart:before { + content: "" +} + +.fa-pie-chart:before { + content: "" +} + +.fa-line-chart:before { + content: "" +} + +.fa-lastfm:before { + content: "" +} + +.fa-lastfm-square:before { + content: "" +} + +.fa-toggle-off:before { + content: "" +} + +.fa-toggle-on:before { + content: "" +} + +.fa-bicycle:before { + content: "" +} + +.fa-bus:before { + content: "" +} + +.fa-ioxhost:before { + content: "" +} + +.fa-angellist:before { + content: "" +} + +.fa-cc:before { + content: "" +} + +.fa-shekel:before, .fa-sheqel:before, .fa-ils:before { + content: "" +} + +.fa-meanpath:before { + content: "" +} + +.fa, .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand, .rst-content .admonition-title, .rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .rst-content p.caption .headerlink, .rst-content tt.download span:first-child, .rst-content code.download span:first-child, .icon, .wy-dropdown .caret, .wy-inline-validate.wy-inline-validate-success .wy-input-context, .wy-inline-validate.wy-inline-validate-danger .wy-input-context, .wy-inline-validate.wy-inline-validate-warning .wy-input-context, .wy-inline-validate.wy-inline-validate-info .wy-input-context { + font-family: inherit +} + +.fa:before, .wy-menu-vertical li span.toctree-expand:before, .wy-menu-vertical li.on a span.toctree-expand:before, .wy-menu-vertical li.current > a span.toctree-expand:before, .rst-content .admonition-title:before, .rst-content h1 .headerlink:before, .rst-content h2 .headerlink:before, .rst-content h3 .headerlink:before, .rst-content h4 .headerlink:before, .rst-content h5 .headerlink:before, .rst-content h6 .headerlink:before, .rst-content dl dt .headerlink:before, .rst-content p.caption .headerlink:before, .rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before, .icon:before, .wy-dropdown .caret:before, .wy-inline-validate.wy-inline-validate-success .wy-input-context:before, .wy-inline-validate.wy-inline-validate-danger .wy-input-context:before, .wy-inline-validate.wy-inline-validate-warning .wy-input-context:before, .wy-inline-validate.wy-inline-validate-info .wy-input-context:before { + font-family: "FontAwesome"; + display: inline-block; + font-style: normal; + font-weight: normal; + line-height: 1; + text-decoration: inherit +} + +a .fa, a .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li a span.toctree-expand, .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand, a .rst-content .admonition-title, .rst-content a .admonition-title, a .rst-content h1 .headerlink, .rst-content h1 a .headerlink, a .rst-content h2 .headerlink, .rst-content h2 a .headerlink, a .rst-content h3 .headerlink, .rst-content h3 a .headerlink, a .rst-content h4 .headerlink, .rst-content h4 a .headerlink, a .rst-content h5 .headerlink, .rst-content h5 a .headerlink, a .rst-content h6 .headerlink, .rst-content h6 a .headerlink, a .rst-content dl dt .headerlink, .rst-content dl dt a .headerlink, a .rst-content p.caption .headerlink, .rst-content p.caption a .headerlink, a .rst-content tt.download span:first-child, .rst-content tt.download a span:first-child, a .rst-content code.download span:first-child, .rst-content code.download a span:first-child, a .icon { + display: inline-block; + text-decoration: inherit +} + +.btn .fa, .btn .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li .btn span.toctree-expand, .btn .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.on a .btn span.toctree-expand, .btn .wy-menu-vertical li.current > a span.toctree-expand, .wy-menu-vertical li.current > a .btn span.toctree-expand, .btn .rst-content .admonition-title, .rst-content .btn .admonition-title, .btn .rst-content h1 .headerlink, .rst-content h1 .btn .headerlink, .btn .rst-content h2 .headerlink, .rst-content h2 .btn .headerlink, .btn .rst-content h3 .headerlink, .rst-content h3 .btn .headerlink, .btn .rst-content h4 .headerlink, .rst-content h4 .btn .headerlink, .btn .rst-content h5 .headerlink, .rst-content h5 .btn .headerlink, .btn .rst-content h6 .headerlink, .rst-content h6 .btn .headerlink, .btn .rst-content dl dt .headerlink, .rst-content dl dt .btn .headerlink, .btn .rst-content p.caption .headerlink, .rst-content p.caption .btn .headerlink, .btn .rst-content tt.download span:first-child, .rst-content tt.download .btn span:first-child, .btn .rst-content code.download span:first-child, .rst-content code.download .btn span:first-child, .btn .icon, .nav .fa, .nav .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li .nav span.toctree-expand, .nav .wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.on a .nav span.toctree-expand, .nav .wy-menu-vertical li.current > a span.toctree-expand, .wy-menu-vertical li.current > a .nav span.toctree-expand, .nav .rst-content .admonition-title, .rst-content .nav .admonition-title, .nav .rst-content h1 .headerlink, .rst-content h1 .nav .headerlink, .nav .rst-content h2 .headerlink, .rst-content h2 .nav .headerlink, .nav .rst-content h3 .headerlink, .rst-content h3 .nav .headerlink, .nav .rst-content h4 .headerlink, .rst-content h4 .nav .headerlink, .nav .rst-content h5 .headerlink, .rst-content h5 .nav .headerlink, .nav .rst-content h6 .headerlink, .rst-content h6 .nav .headerlink, .nav .rst-content dl dt .headerlink, .rst-content dl dt .nav .headerlink, .nav .rst-content p.caption .headerlink, .rst-content p.caption .nav .headerlink, .nav .rst-content tt.download span:first-child, .rst-content tt.download .nav span:first-child, .nav .rst-content code.download span:first-child, .rst-content code.download .nav span:first-child, .nav .icon { + display: inline +} + +.btn .fa.fa-large, .btn .wy-menu-vertical li span.fa-large.toctree-expand, .wy-menu-vertical li .btn span.fa-large.toctree-expand, .btn .rst-content .fa-large.admonition-title, .rst-content .btn .fa-large.admonition-title, .btn .rst-content h1 .fa-large.headerlink, .rst-content h1 .btn .fa-large.headerlink, .btn .rst-content h2 .fa-large.headerlink, .rst-content h2 .btn .fa-large.headerlink, .btn .rst-content h3 .fa-large.headerlink, .rst-content h3 .btn .fa-large.headerlink, .btn .rst-content h4 .fa-large.headerlink, .rst-content h4 .btn .fa-large.headerlink, .btn .rst-content h5 .fa-large.headerlink, .rst-content h5 .btn .fa-large.headerlink, .btn .rst-content h6 .fa-large.headerlink, .rst-content h6 .btn .fa-large.headerlink, .btn .rst-content dl dt .fa-large.headerlink, .rst-content dl dt .btn .fa-large.headerlink, .btn .rst-content p.caption .fa-large.headerlink, .rst-content p.caption .btn .fa-large.headerlink, .btn .rst-content tt.download span.fa-large:first-child, .rst-content tt.download .btn span.fa-large:first-child, .btn .rst-content code.download span.fa-large:first-child, .rst-content code.download .btn span.fa-large:first-child, .btn .fa-large.icon, .nav .fa.fa-large, .nav .wy-menu-vertical li span.fa-large.toctree-expand, .wy-menu-vertical li .nav span.fa-large.toctree-expand, .nav .rst-content .fa-large.admonition-title, .rst-content .nav .fa-large.admonition-title, .nav .rst-content h1 .fa-large.headerlink, .rst-content h1 .nav .fa-large.headerlink, .nav .rst-content h2 .fa-large.headerlink, .rst-content h2 .nav .fa-large.headerlink, .nav .rst-content h3 .fa-large.headerlink, .rst-content h3 .nav .fa-large.headerlink, .nav .rst-content h4 .fa-large.headerlink, .rst-content h4 .nav .fa-large.headerlink, .nav .rst-content h5 .fa-large.headerlink, .rst-content h5 .nav .fa-large.headerlink, .nav .rst-content h6 .fa-large.headerlink, .rst-content h6 .nav .fa-large.headerlink, .nav .rst-content dl dt .fa-large.headerlink, .rst-content dl dt .nav .fa-large.headerlink, .nav .rst-content p.caption .fa-large.headerlink, .rst-content p.caption .nav .fa-large.headerlink, .nav .rst-content tt.download span.fa-large:first-child, .rst-content tt.download .nav span.fa-large:first-child, .nav .rst-content code.download span.fa-large:first-child, .rst-content code.download .nav span.fa-large:first-child, .nav .fa-large.icon { + line-height: 0.9em +} + +.btn .fa.fa-spin, .btn .wy-menu-vertical li span.fa-spin.toctree-expand, .wy-menu-vertical li .btn span.fa-spin.toctree-expand, .btn .rst-content .fa-spin.admonition-title, .rst-content .btn .fa-spin.admonition-title, .btn .rst-content h1 .fa-spin.headerlink, .rst-content h1 .btn .fa-spin.headerlink, .btn .rst-content h2 .fa-spin.headerlink, .rst-content h2 .btn .fa-spin.headerlink, .btn .rst-content h3 .fa-spin.headerlink, .rst-content h3 .btn .fa-spin.headerlink, .btn .rst-content h4 .fa-spin.headerlink, .rst-content h4 .btn .fa-spin.headerlink, .btn .rst-content h5 .fa-spin.headerlink, .rst-content h5 .btn .fa-spin.headerlink, .btn .rst-content h6 .fa-spin.headerlink, .rst-content h6 .btn .fa-spin.headerlink, .btn .rst-content dl dt .fa-spin.headerlink, .rst-content dl dt .btn .fa-spin.headerlink, .btn .rst-content p.caption .fa-spin.headerlink, .rst-content p.caption .btn .fa-spin.headerlink, .btn .rst-content tt.download span.fa-spin:first-child, .rst-content tt.download .btn span.fa-spin:first-child, .btn .rst-content code.download span.fa-spin:first-child, .rst-content code.download .btn span.fa-spin:first-child, .btn .fa-spin.icon, .nav .fa.fa-spin, .nav .wy-menu-vertical li span.fa-spin.toctree-expand, .wy-menu-vertical li .nav span.fa-spin.toctree-expand, .nav .rst-content .fa-spin.admonition-title, .rst-content .nav .fa-spin.admonition-title, .nav .rst-content h1 .fa-spin.headerlink, .rst-content h1 .nav .fa-spin.headerlink, .nav .rst-content h2 .fa-spin.headerlink, .rst-content h2 .nav .fa-spin.headerlink, .nav .rst-content h3 .fa-spin.headerlink, .rst-content h3 .nav .fa-spin.headerlink, .nav .rst-content h4 .fa-spin.headerlink, .rst-content h4 .nav .fa-spin.headerlink, .nav .rst-content h5 .fa-spin.headerlink, .rst-content h5 .nav .fa-spin.headerlink, .nav .rst-content h6 .fa-spin.headerlink, .rst-content h6 .nav .fa-spin.headerlink, .nav .rst-content dl dt .fa-spin.headerlink, .rst-content dl dt .nav .fa-spin.headerlink, .nav .rst-content p.caption .fa-spin.headerlink, .rst-content p.caption .nav .fa-spin.headerlink, .nav .rst-content tt.download span.fa-spin:first-child, .rst-content tt.download .nav span.fa-spin:first-child, .nav .rst-content code.download span.fa-spin:first-child, .rst-content code.download .nav span.fa-spin:first-child, .nav .fa-spin.icon { + display: inline-block +} + +.btn.fa:before, .wy-menu-vertical li span.btn.toctree-expand:before, .rst-content .btn.admonition-title:before, .rst-content h1 .btn.headerlink:before, .rst-content h2 .btn.headerlink:before, .rst-content h3 .btn.headerlink:before, .rst-content h4 .btn.headerlink:before, .rst-content h5 .btn.headerlink:before, .rst-content h6 .btn.headerlink:before, .rst-content dl dt .btn.headerlink:before, .rst-content p.caption .btn.headerlink:before, .rst-content tt.download span.btn:first-child:before, .rst-content code.download span.btn:first-child:before, .btn.icon:before { + opacity: 0.5; + -webkit-transition: opacity 0.05s ease-in; + -moz-transition: opacity 0.05s ease-in; + transition: opacity 0.05s ease-in +} + +.btn.fa:hover:before, .wy-menu-vertical li span.btn.toctree-expand:hover:before, .rst-content .btn.admonition-title:hover:before, .rst-content h1 .btn.headerlink:hover:before, .rst-content h2 .btn.headerlink:hover:before, .rst-content h3 .btn.headerlink:hover:before, .rst-content h4 .btn.headerlink:hover:before, .rst-content h5 .btn.headerlink:hover:before, .rst-content h6 .btn.headerlink:hover:before, .rst-content dl dt .btn.headerlink:hover:before, .rst-content p.caption .btn.headerlink:hover:before, .rst-content tt.download span.btn:first-child:hover:before, .rst-content code.download span.btn:first-child:hover:before, .btn.icon:hover:before { + opacity: 1 +} + +.btn-mini .fa:before, .btn-mini .wy-menu-vertical li span.toctree-expand:before, .wy-menu-vertical li .btn-mini span.toctree-expand:before, .btn-mini .rst-content .admonition-title:before, .rst-content .btn-mini .admonition-title:before, .btn-mini .rst-content h1 .headerlink:before, .rst-content h1 .btn-mini .headerlink:before, .btn-mini .rst-content h2 .headerlink:before, .rst-content h2 .btn-mini .headerlink:before, .btn-mini .rst-content h3 .headerlink:before, .rst-content h3 .btn-mini .headerlink:before, .btn-mini .rst-content h4 .headerlink:before, .rst-content h4 .btn-mini .headerlink:before, .btn-mini .rst-content h5 .headerlink:before, .rst-content h5 .btn-mini .headerlink:before, .btn-mini .rst-content h6 .headerlink:before, .rst-content h6 .btn-mini .headerlink:before, .btn-mini .rst-content dl dt .headerlink:before, .rst-content dl dt .btn-mini .headerlink:before, .btn-mini .rst-content p.caption .headerlink:before, .rst-content p.caption .btn-mini .headerlink:before, .btn-mini .rst-content tt.download span:first-child:before, .rst-content tt.download .btn-mini span:first-child:before, .btn-mini .rst-content code.download span:first-child:before, .rst-content code.download .btn-mini span:first-child:before, .btn-mini .icon:before { + font-size: 14px; + vertical-align: -15% +} + +.wy-alert, .rst-content .note, .rst-content .attention, .rst-content .caution, .rst-content .danger, .rst-content .error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .warning, .rst-content .seealso, .rst-content .admonition-todo { + padding: 12px; + line-height: 24px; + margin-bottom: 24px; + background: #e7f2fa +} + +.wy-alert-title, .rst-content .admonition-title { + color: #fff; + font-weight: bold; + display: block; + color: #fff; + background: #6ab0de; + margin: -12px; + padding: 6px 12px; + margin-bottom: 12px +} + +.wy-alert.wy-alert-danger, .rst-content .wy-alert-danger.note, .rst-content .wy-alert-danger.attention, .rst-content .wy-alert-danger.caution, .rst-content .danger, .rst-content .error, .rst-content .wy-alert-danger.hint, .rst-content .wy-alert-danger.important, .rst-content .wy-alert-danger.tip, .rst-content .wy-alert-danger.warning, .rst-content .wy-alert-danger.seealso, .rst-content .wy-alert-danger.admonition-todo { + background: #fdf3f2 +} + +.wy-alert.wy-alert-danger .wy-alert-title, .rst-content .wy-alert-danger.note .wy-alert-title, .rst-content .wy-alert-danger.attention .wy-alert-title, .rst-content .wy-alert-danger.caution .wy-alert-title, .rst-content .danger .wy-alert-title, .rst-content .error .wy-alert-title, .rst-content .wy-alert-danger.hint .wy-alert-title, .rst-content .wy-alert-danger.important .wy-alert-title, .rst-content .wy-alert-danger.tip .wy-alert-title, .rst-content .wy-alert-danger.warning .wy-alert-title, .rst-content .wy-alert-danger.seealso .wy-alert-title, .rst-content .wy-alert-danger.admonition-todo .wy-alert-title, .wy-alert.wy-alert-danger .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-danger .admonition-title, .rst-content .wy-alert-danger.note .admonition-title, .rst-content .wy-alert-danger.attention .admonition-title, .rst-content .wy-alert-danger.caution .admonition-title, .rst-content .danger .admonition-title, .rst-content .error .admonition-title, .rst-content .wy-alert-danger.hint .admonition-title, .rst-content .wy-alert-danger.important .admonition-title, .rst-content .wy-alert-danger.tip .admonition-title, .rst-content .wy-alert-danger.warning .admonition-title, .rst-content .wy-alert-danger.seealso .admonition-title, .rst-content .wy-alert-danger.admonition-todo .admonition-title { + background: #f29f97 +} + +.wy-alert.wy-alert-warning, .rst-content .wy-alert-warning.note, .rst-content .attention, .rst-content .caution, .rst-content .wy-alert-warning.danger, .rst-content .wy-alert-warning.error, .rst-content .wy-alert-warning.hint, .rst-content .wy-alert-warning.important, .rst-content .wy-alert-warning.tip, .rst-content .warning, .rst-content .wy-alert-warning.seealso, .rst-content .admonition-todo { + background: #ffedcc +} + +.wy-alert.wy-alert-warning .wy-alert-title, .rst-content .wy-alert-warning.note .wy-alert-title, .rst-content .attention .wy-alert-title, .rst-content .caution .wy-alert-title, .rst-content .wy-alert-warning.danger .wy-alert-title, .rst-content .wy-alert-warning.error .wy-alert-title, .rst-content .wy-alert-warning.hint .wy-alert-title, .rst-content .wy-alert-warning.important .wy-alert-title, .rst-content .wy-alert-warning.tip .wy-alert-title, .rst-content .warning .wy-alert-title, .rst-content .wy-alert-warning.seealso .wy-alert-title, .rst-content .admonition-todo .wy-alert-title, .wy-alert.wy-alert-warning .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-warning .admonition-title, .rst-content .wy-alert-warning.note .admonition-title, .rst-content .attention .admonition-title, .rst-content .caution .admonition-title, .rst-content .wy-alert-warning.danger .admonition-title, .rst-content .wy-alert-warning.error .admonition-title, .rst-content .wy-alert-warning.hint .admonition-title, .rst-content .wy-alert-warning.important .admonition-title, .rst-content .wy-alert-warning.tip .admonition-title, .rst-content .warning .admonition-title, .rst-content .wy-alert-warning.seealso .admonition-title, .rst-content .admonition-todo .admonition-title { + background: #f0b37e +} + +.wy-alert.wy-alert-info, .rst-content .note, .rst-content .wy-alert-info.attention, .rst-content .wy-alert-info.caution, .rst-content .wy-alert-info.danger, .rst-content .wy-alert-info.error, .rst-content .wy-alert-info.hint, .rst-content .wy-alert-info.important, .rst-content .wy-alert-info.tip, .rst-content .wy-alert-info.warning, .rst-content .seealso, .rst-content .wy-alert-info.admonition-todo { + background: #e7f2fa +} + +.wy-alert.wy-alert-info .wy-alert-title, .rst-content .note .wy-alert-title, .rst-content .wy-alert-info.attention .wy-alert-title, .rst-content .wy-alert-info.caution .wy-alert-title, .rst-content .wy-alert-info.danger .wy-alert-title, .rst-content .wy-alert-info.error .wy-alert-title, .rst-content .wy-alert-info.hint .wy-alert-title, .rst-content .wy-alert-info.important .wy-alert-title, .rst-content .wy-alert-info.tip .wy-alert-title, .rst-content .wy-alert-info.warning .wy-alert-title, .rst-content .seealso .wy-alert-title, .rst-content .wy-alert-info.admonition-todo .wy-alert-title, .wy-alert.wy-alert-info .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-info .admonition-title, .rst-content .note .admonition-title, .rst-content .wy-alert-info.attention .admonition-title, .rst-content .wy-alert-info.caution .admonition-title, .rst-content .wy-alert-info.danger .admonition-title, .rst-content .wy-alert-info.error .admonition-title, .rst-content .wy-alert-info.hint .admonition-title, .rst-content .wy-alert-info.important .admonition-title, .rst-content .wy-alert-info.tip .admonition-title, .rst-content .wy-alert-info.warning .admonition-title, .rst-content .seealso .admonition-title, .rst-content .wy-alert-info.admonition-todo .admonition-title { + background: #6ab0de +} + +.wy-alert.wy-alert-success, .rst-content .wy-alert-success.note, .rst-content .wy-alert-success.attention, .rst-content .wy-alert-success.caution, .rst-content .wy-alert-success.danger, .rst-content .wy-alert-success.error, .rst-content .hint, .rst-content .important, .rst-content .tip, .rst-content .wy-alert-success.warning, .rst-content .wy-alert-success.seealso, .rst-content .wy-alert-success.admonition-todo { + background: #dbfaf4 +} + +.wy-alert.wy-alert-success .wy-alert-title, .rst-content .wy-alert-success.note .wy-alert-title, .rst-content .wy-alert-success.attention .wy-alert-title, .rst-content .wy-alert-success.caution .wy-alert-title, .rst-content .wy-alert-success.danger .wy-alert-title, .rst-content .wy-alert-success.error .wy-alert-title, .rst-content .hint .wy-alert-title, .rst-content .important .wy-alert-title, .rst-content .tip .wy-alert-title, .rst-content .wy-alert-success.warning .wy-alert-title, .rst-content .wy-alert-success.seealso .wy-alert-title, .rst-content .wy-alert-success.admonition-todo .wy-alert-title, .wy-alert.wy-alert-success .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-success .admonition-title, .rst-content .wy-alert-success.note .admonition-title, .rst-content .wy-alert-success.attention .admonition-title, .rst-content .wy-alert-success.caution .admonition-title, .rst-content .wy-alert-success.danger .admonition-title, .rst-content .wy-alert-success.error .admonition-title, .rst-content .hint .admonition-title, .rst-content .important .admonition-title, .rst-content .tip .admonition-title, .rst-content .wy-alert-success.warning .admonition-title, .rst-content .wy-alert-success.seealso .admonition-title, .rst-content .wy-alert-success.admonition-todo .admonition-title { + background: #1abc9c +} + +.wy-alert.wy-alert-neutral, .rst-content .wy-alert-neutral.note, .rst-content .wy-alert-neutral.attention, .rst-content .wy-alert-neutral.caution, .rst-content .wy-alert-neutral.danger, .rst-content .wy-alert-neutral.error, .rst-content .wy-alert-neutral.hint, .rst-content .wy-alert-neutral.important, .rst-content .wy-alert-neutral.tip, .rst-content .wy-alert-neutral.warning, .rst-content .wy-alert-neutral.seealso, .rst-content .wy-alert-neutral.admonition-todo { + background: #f3f6f6 +} + +.wy-alert.wy-alert-neutral .wy-alert-title, .rst-content .wy-alert-neutral.note .wy-alert-title, .rst-content .wy-alert-neutral.attention .wy-alert-title, .rst-content .wy-alert-neutral.caution .wy-alert-title, .rst-content .wy-alert-neutral.danger .wy-alert-title, .rst-content .wy-alert-neutral.error .wy-alert-title, .rst-content .wy-alert-neutral.hint .wy-alert-title, .rst-content .wy-alert-neutral.important .wy-alert-title, .rst-content .wy-alert-neutral.tip .wy-alert-title, .rst-content .wy-alert-neutral.warning .wy-alert-title, .rst-content .wy-alert-neutral.seealso .wy-alert-title, .rst-content .wy-alert-neutral.admonition-todo .wy-alert-title, .wy-alert.wy-alert-neutral .rst-content .admonition-title, .rst-content .wy-alert.wy-alert-neutral .admonition-title, .rst-content .wy-alert-neutral.note .admonition-title, .rst-content .wy-alert-neutral.attention .admonition-title, .rst-content .wy-alert-neutral.caution .admonition-title, .rst-content .wy-alert-neutral.danger .admonition-title, .rst-content .wy-alert-neutral.error .admonition-title, .rst-content .wy-alert-neutral.hint .admonition-title, .rst-content .wy-alert-neutral.important .admonition-title, .rst-content .wy-alert-neutral.tip .admonition-title, .rst-content .wy-alert-neutral.warning .admonition-title, .rst-content .wy-alert-neutral.seealso .admonition-title, .rst-content .wy-alert-neutral.admonition-todo .admonition-title { + color: #404040; + background: #e1e4e5 +} + +.wy-alert.wy-alert-neutral a, .rst-content .wy-alert-neutral.note a, .rst-content .wy-alert-neutral.attention a, .rst-content .wy-alert-neutral.caution a, .rst-content .wy-alert-neutral.danger a, .rst-content .wy-alert-neutral.error a, .rst-content .wy-alert-neutral.hint a, .rst-content .wy-alert-neutral.important a, .rst-content .wy-alert-neutral.tip a, .rst-content .wy-alert-neutral.warning a, .rst-content .wy-alert-neutral.seealso a, .rst-content .wy-alert-neutral.admonition-todo a { + color: #2980B9 +} + +.wy-alert p:last-child, .rst-content .note p:last-child, .rst-content .attention p:last-child, .rst-content .caution p:last-child, .rst-content .danger p:last-child, .rst-content .error p:last-child, .rst-content .hint p:last-child, .rst-content .important p:last-child, .rst-content .tip p:last-child, .rst-content .warning p:last-child, .rst-content .seealso p:last-child, .rst-content .admonition-todo p:last-child { + margin-bottom: 0 +} + +.wy-tray-container { + position: fixed; + bottom: 0px; + left: 0; + z-index: 600 +} + +.wy-tray-container li { + display: block; + width: 300px; + background: transparent; + color: #fff; + text-align: center; + box-shadow: 0 5px 5px 0 rgba(0, 0, 0, 0.1); + padding: 0 24px; + min-width: 20%; + opacity: 0; + height: 0; + line-height: 56px; + overflow: hidden; + -webkit-transition: all 0.3s ease-in; + -moz-transition: all 0.3s ease-in; + transition: all 0.3s ease-in +} + +.wy-tray-container li.wy-tray-item-success { + background: #27AE60 +} + +.wy-tray-container li.wy-tray-item-info { + background: #2980B9 +} + +.wy-tray-container li.wy-tray-item-warning { + background: #E67E22 +} + +.wy-tray-container li.wy-tray-item-danger { + background: #E74C3C +} + +.wy-tray-container li.on { + opacity: 1; + height: 56px +} + +@media screen and (max-width: 768px) { + .wy-tray-container { + bottom: auto; + top: 0; + width: 100% + } + + .wy-tray-container li { + width: 100% + } +} + +button { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; + cursor: pointer; + line-height: normal; + -webkit-appearance: button; + *overflow: visible +} + +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0 +} + +button[disabled] { + cursor: default +} + +.btn { + display: inline-block; + border-radius: 2px; + line-height: normal; + white-space: nowrap; + text-align: center; + cursor: pointer; + font-size: 100%; + padding: 6px 12px 8px 12px; + color: #fff; + border: 1px solid rgba(0, 0, 0, 0.1); + background-color: #27AE60; + text-decoration: none; + font-weight: normal; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + box-shadow: 0px 1px 2px -1px rgba(255, 255, 255, 0.5) inset, 0px -2px 0px 0px rgba(0, 0, 0, 0.1) inset; + outline-none: false; + vertical-align: middle; + *display: inline; + zoom: 1; + -webkit-user-drag: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-transition: all 0.1s linear; + -moz-transition: all 0.1s linear; + transition: all 0.1s linear +} + +.btn-hover { + background: #2e8ece; + color: #fff +} + +.btn:hover { + background: #2cc36b; + color: #fff +} + +.btn:focus { + background: #2cc36b; + outline: 0 +} + +.btn:active { + box-shadow: 0px -1px 0px 0px rgba(0, 0, 0, 0.05) inset, 0px 2px 0px 0px rgba(0, 0, 0, 0.1) inset; + padding: 8px 12px 6px 12px +} + +.btn:visited { + color: #fff +} + +.btn:disabled { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none +} + +.btn-disabled { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none +} + +.btn-disabled:hover, .btn-disabled:focus, .btn-disabled:active { + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + filter: alpha(opacity=40); + opacity: 0.4; + cursor: not-allowed; + box-shadow: none +} + +.btn::-moz-focus-inner { + padding: 0; + border: 0 +} + +.btn-small { + font-size: 80% +} + +.btn-info { + background-color: #2980B9 !important +} + +.btn-info:hover { + background-color: #2e8ece !important +} + +.btn-neutral { + background-color: #f3f6f6 !important; + color: #404040 !important +} + +.btn-neutral:hover { + background-color: #e5ebeb !important; + color: #404040 +} + +.btn-neutral:visited { + color: #404040 !important +} + +.btn-success { + background-color: #27AE60 !important +} + +.btn-success:hover { + background-color: #295 !important +} + +.btn-danger { + background-color: #E74C3C !important +} + +.btn-danger:hover { + background-color: #ea6153 !important +} + +.btn-warning { + background-color: #E67E22 !important +} + +.btn-warning:hover { + background-color: #e98b39 !important +} + +.btn-invert { + background-color: #222 +} + +.btn-invert:hover { + background-color: #2f2f2f !important +} + +.btn-link { + background-color: transparent !important; + color: #2980B9; + box-shadow: none; + border-color: transparent !important +} + +.btn-link:hover { + background-color: transparent !important; + color: #409ad5 !important; + box-shadow: none +} + +.btn-link:active { + background-color: transparent !important; + color: #409ad5 !important; + box-shadow: none +} + +.btn-link:visited { + color: #9B59B6 +} + +.wy-btn-group .btn, .wy-control .btn { + vertical-align: middle +} + +.wy-btn-group { + margin-bottom: 24px; + *zoom: 1 +} + +.wy-btn-group:before, .wy-btn-group:after { + display: table; + content: "" +} + +.wy-btn-group:after { + clear: both +} + +.wy-dropdown { + position: relative; + display: inline-block +} + +.wy-dropdown-active .wy-dropdown-menu { + display: block +} + +.wy-dropdown-menu { + position: absolute; + left: 0; + display: none; + float: left; + top: 100%; + min-width: 100%; + background: #fcfcfc; + z-index: 100; + border: solid 1px #cfd7dd; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1); + padding: 12px +} + +.wy-dropdown-menu > dd > a { + display: block; + clear: both; + color: #404040; + white-space: nowrap; + font-size: 90%; + padding: 0 12px; + cursor: pointer +} + +.wy-dropdown-menu > dd > a:hover { + background: #2980B9; + color: #fff +} + +.wy-dropdown-menu > dd.divider { + border-top: solid 1px #cfd7dd; + margin: 6px 0 +} + +.wy-dropdown-menu > dd.search { + padding-bottom: 12px +} + +.wy-dropdown-menu > dd.search input[type="search"] { + width: 100% +} + +.wy-dropdown-menu > dd.call-to-action { + background: #e3e3e3; + text-transform: uppercase; + font-weight: 500; + font-size: 80% +} + +.wy-dropdown-menu > dd.call-to-action:hover { + background: #e3e3e3 +} + +.wy-dropdown-menu > dd.call-to-action .btn { + color: #fff +} + +.wy-dropdown.wy-dropdown-up .wy-dropdown-menu { + bottom: 100%; + top: auto; + left: auto; + right: 0 +} + +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu { + background: #fcfcfc; + margin-top: 2px +} + +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a { + padding: 6px 12px +} + +.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover { + background: #2980B9; + color: #fff +} + +.wy-dropdown.wy-dropdown-left .wy-dropdown-menu { + right: 0; + left: auto; + text-align: right +} + +.wy-dropdown-arrow:before { + content: " "; + border-bottom: 5px solid #f5f5f5; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + position: absolute; + display: block; + top: -4px; + left: 50%; + margin-left: -3px +} + +.wy-dropdown-arrow.wy-dropdown-arrow-left:before { + left: 11px +} + +.wy-form-stacked select { + display: block +} + +.wy-form-aligned input, .wy-form-aligned textarea, .wy-form-aligned select, .wy-form-aligned .wy-help-inline, .wy-form-aligned label { + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle +} + +.wy-form-aligned .wy-control-group > label { + display: inline-block; + vertical-align: middle; + width: 10em; + margin: 6px 12px 0 0; + float: left +} + +.wy-form-aligned .wy-control { + float: left +} + +.wy-form-aligned .wy-control label { + display: block +} + +.wy-form-aligned .wy-control select { + margin-top: 6px +} + +fieldset { + border: 0; + margin: 0; + padding: 0 +} + +legend { + display: block; + width: 100%; + border: 0; + padding: 0; + white-space: normal; + margin-bottom: 24px; + font-size: 150%; + *margin-left: -7px +} + +label { + display: block; + margin: 0 0 0.3125em 0; + color: #333; + font-size: 90% +} + +input, select, textarea { + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle +} + +.wy-control-group { + margin-bottom: 24px; + *zoom: 1; + max-width: 68em; + margin-left: auto; + margin-right: auto; + *zoom: 1 +} + +.wy-control-group:before, .wy-control-group:after { + display: table; + content: "" +} + +.wy-control-group:after { + clear: both +} + +.wy-control-group:before, .wy-control-group:after { + display: table; + content: "" +} + +.wy-control-group:after { + clear: both +} + +.wy-control-group.wy-control-group-required > label:after { + content: " *"; + color: #E74C3C +} + +.wy-control-group .wy-form-full, .wy-control-group .wy-form-halves, .wy-control-group .wy-form-thirds { + padding-bottom: 12px +} + +.wy-control-group .wy-form-full select, .wy-control-group .wy-form-halves select, .wy-control-group .wy-form-thirds select { + width: 100% +} + +.wy-control-group .wy-form-full input[type="text"], .wy-control-group .wy-form-full input[type="password"], .wy-control-group .wy-form-full input[type="email"], .wy-control-group .wy-form-full input[type="url"], .wy-control-group .wy-form-full input[type="date"], .wy-control-group .wy-form-full input[type="month"], .wy-control-group .wy-form-full input[type="time"], .wy-control-group .wy-form-full input[type="datetime"], .wy-control-group .wy-form-full input[type="datetime-local"], .wy-control-group .wy-form-full input[type="week"], .wy-control-group .wy-form-full input[type="number"], .wy-control-group .wy-form-full input[type="search"], .wy-control-group .wy-form-full input[type="tel"], .wy-control-group .wy-form-full input[type="color"], .wy-control-group .wy-form-halves input[type="text"], .wy-control-group .wy-form-halves input[type="password"], .wy-control-group .wy-form-halves input[type="email"], .wy-control-group .wy-form-halves input[type="url"], .wy-control-group .wy-form-halves input[type="date"], .wy-control-group .wy-form-halves input[type="month"], .wy-control-group .wy-form-halves input[type="time"], .wy-control-group .wy-form-halves input[type="datetime"], .wy-control-group .wy-form-halves input[type="datetime-local"], .wy-control-group .wy-form-halves input[type="week"], .wy-control-group .wy-form-halves input[type="number"], .wy-control-group .wy-form-halves input[type="search"], .wy-control-group .wy-form-halves input[type="tel"], .wy-control-group .wy-form-halves input[type="color"], .wy-control-group .wy-form-thirds input[type="text"], .wy-control-group .wy-form-thirds input[type="password"], .wy-control-group .wy-form-thirds input[type="email"], .wy-control-group .wy-form-thirds input[type="url"], .wy-control-group .wy-form-thirds input[type="date"], .wy-control-group .wy-form-thirds input[type="month"], .wy-control-group .wy-form-thirds input[type="time"], .wy-control-group .wy-form-thirds input[type="datetime"], .wy-control-group .wy-form-thirds input[type="datetime-local"], .wy-control-group .wy-form-thirds input[type="week"], .wy-control-group .wy-form-thirds input[type="number"], .wy-control-group .wy-form-thirds input[type="search"], .wy-control-group .wy-form-thirds input[type="tel"], .wy-control-group .wy-form-thirds input[type="color"] { + width: 100% +} + +.wy-control-group .wy-form-full { + float: left; + display: block; + margin-right: 2.35765%; + width: 100%; + margin-right: 0 +} + +.wy-control-group .wy-form-full:last-child { + margin-right: 0 +} + +.wy-control-group .wy-form-halves { + float: left; + display: block; + margin-right: 2.35765%; + width: 48.82117% +} + +.wy-control-group .wy-form-halves:last-child { + margin-right: 0 +} + +.wy-control-group .wy-form-halves:nth-of-type(2n) { + margin-right: 0 +} + +.wy-control-group .wy-form-halves:nth-of-type(2n+1) { + clear: left +} + +.wy-control-group .wy-form-thirds { + float: left; + display: block; + margin-right: 2.35765%; + width: 31.76157% +} + +.wy-control-group .wy-form-thirds:last-child { + margin-right: 0 +} + +.wy-control-group .wy-form-thirds:nth-of-type(3n) { + margin-right: 0 +} + +.wy-control-group .wy-form-thirds:nth-of-type(3n+1) { + clear: left +} + +.wy-control-group.wy-control-group-no-input .wy-control { + margin: 6px 0 0 0; + font-size: 90% +} + +.wy-control-no-input { + display: inline-block; + margin: 6px 0 0 0; + font-size: 90% +} + +.wy-control-group.fluid-input input[type="text"], .wy-control-group.fluid-input input[type="password"], .wy-control-group.fluid-input input[type="email"], .wy-control-group.fluid-input input[type="url"], .wy-control-group.fluid-input input[type="date"], .wy-control-group.fluid-input input[type="month"], .wy-control-group.fluid-input input[type="time"], .wy-control-group.fluid-input input[type="datetime"], .wy-control-group.fluid-input input[type="datetime-local"], .wy-control-group.fluid-input input[type="week"], .wy-control-group.fluid-input input[type="number"], .wy-control-group.fluid-input input[type="search"], .wy-control-group.fluid-input input[type="tel"], .wy-control-group.fluid-input input[type="color"] { + width: 100% +} + +.wy-form-message-inline { + display: inline-block; + padding-left: 0.3em; + color: #666; + vertical-align: middle; + font-size: 90% +} + +.wy-form-message { + display: block; + color: #999; + font-size: 70%; + margin-top: 0.3125em; + font-style: italic +} + +.wy-form-message p { + font-size: inherit; + font-style: italic; + margin-bottom: 6px +} + +.wy-form-message p:last-child { + margin-bottom: 0 +} + +input { + line-height: normal +} + +input[type="button"], input[type="reset"], input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + *overflow: visible +} + +input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="date"], input[type="month"], input[type="time"], input[type="datetime"], input[type="datetime-local"], input[type="week"], input[type="number"], input[type="search"], input[type="tel"], input[type="color"] { + -webkit-appearance: none; + padding: 6px; + display: inline-block; + border: 1px solid #ccc; + font-size: 80%; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + box-shadow: inset 0 1px 3px #ddd; + border-radius: 0; + -webkit-transition: border 0.3s linear; + -moz-transition: border 0.3s linear; + transition: border 0.3s linear +} + +input[type="datetime-local"] { + padding: 0.34375em 0.625em +} + +input[disabled] { + cursor: default +} + +input[type="checkbox"], input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; + margin-right: 0.3125em; + *height: 13px; + *width: 13px +} + +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none +} + +input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus { + outline: 0; + outline: thin dotted \9; + border-color: #333 +} + +input.no-focus:focus { + border-color: #ccc !important +} + +input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 1px auto #129FEA +} + +input[type="text"][disabled], input[type="password"][disabled], input[type="email"][disabled], input[type="url"][disabled], input[type="date"][disabled], input[type="month"][disabled], input[type="time"][disabled], input[type="datetime"][disabled], input[type="datetime-local"][disabled], input[type="week"][disabled], input[type="number"][disabled], input[type="search"][disabled], input[type="tel"][disabled], input[type="color"][disabled] { + cursor: not-allowed; + background-color: #fafafa +} + +input:focus:invalid, textarea:focus:invalid, select:focus:invalid { + color: #E74C3C; + border: 1px solid #E74C3C +} + +input:focus:invalid:focus, textarea:focus:invalid:focus, select:focus:invalid:focus { + border-color: #E74C3C +} + +input[type="file"]:focus:invalid:focus, input[type="radio"]:focus:invalid:focus, input[type="checkbox"]:focus:invalid:focus { + outline-color: #E74C3C +} + +input.wy-input-large { + padding: 12px; + font-size: 100% +} + +textarea { + overflow: auto; + vertical-align: top; + width: 100%; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif +} + +select, textarea { + padding: 0.5em 0.625em; + display: inline-block; + border: 1px solid #ccc; + font-size: 80%; + box-shadow: inset 0 1px 3px #ddd; + -webkit-transition: border 0.3s linear; + -moz-transition: border 0.3s linear; + transition: border 0.3s linear +} + +select { + border: 1px solid #ccc; + background-color: #fff +} + +select[multiple] { + height: auto +} + +select:focus, textarea:focus { + outline: 0 +} + +select[disabled], textarea[disabled], input[readonly], select[readonly], textarea[readonly] { + cursor: not-allowed; + background-color: #fafafa +} + +input[type="radio"][disabled], input[type="checkbox"][disabled] { + cursor: not-allowed +} + +.wy-checkbox, .wy-radio { + margin: 6px 0; + color: #404040; + display: block +} + +.wy-checkbox input, .wy-radio input { + vertical-align: baseline +} + +.wy-form-message-inline { + display: inline-block; + *display: inline; + *zoom: 1; + vertical-align: middle +} + +.wy-input-prefix, .wy-input-suffix { + white-space: nowrap; + padding: 6px +} + +.wy-input-prefix .wy-input-context, .wy-input-suffix .wy-input-context { + line-height: 27px; + padding: 0 8px; + display: inline-block; + font-size: 80%; + background-color: #f3f6f6; + border: solid 1px #ccc; + color: #999 +} + +.wy-input-suffix .wy-input-context { + border-left: 0 +} + +.wy-input-prefix .wy-input-context { + border-right: 0 +} + +.wy-switch { + width: 36px; + height: 12px; + margin: 12px 0; + position: relative; + border-radius: 4px; + background: #ccc; + cursor: pointer; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out +} + +.wy-switch:before { + position: absolute; + content: ""; + display: block; + width: 18px; + height: 18px; + border-radius: 4px; + background: #999; + left: -3px; + top: -3px; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out +} + +.wy-switch:after { + content: "false"; + position: absolute; + left: 48px; + display: block; + font-size: 12px; + color: #ccc +} + +.wy-switch.active { + background: #1e8449 +} + +.wy-switch.active:before { + left: 24px; + background: #27AE60 +} + +.wy-switch.active:after { + content: "true" +} + +.wy-switch.disabled, .wy-switch.active.disabled { + cursor: not-allowed +} + +.wy-control-group.wy-control-group-error .wy-form-message, .wy-control-group.wy-control-group-error > label { + color: #E74C3C +} + +.wy-control-group.wy-control-group-error input[type="text"], .wy-control-group.wy-control-group-error input[type="password"], .wy-control-group.wy-control-group-error input[type="email"], .wy-control-group.wy-control-group-error input[type="url"], .wy-control-group.wy-control-group-error input[type="date"], .wy-control-group.wy-control-group-error input[type="month"], .wy-control-group.wy-control-group-error input[type="time"], .wy-control-group.wy-control-group-error input[type="datetime"], .wy-control-group.wy-control-group-error input[type="datetime-local"], .wy-control-group.wy-control-group-error input[type="week"], .wy-control-group.wy-control-group-error input[type="number"], .wy-control-group.wy-control-group-error input[type="search"], .wy-control-group.wy-control-group-error input[type="tel"], .wy-control-group.wy-control-group-error input[type="color"] { + border: solid 1px #E74C3C +} + +.wy-control-group.wy-control-group-error textarea { + border: solid 1px #E74C3C +} + +.wy-inline-validate { + white-space: nowrap +} + +.wy-inline-validate .wy-input-context { + padding: 0.5em 0.625em; + display: inline-block; + font-size: 80% +} + +.wy-inline-validate.wy-inline-validate-success .wy-input-context { + color: #27AE60 +} + +.wy-inline-validate.wy-inline-validate-danger .wy-input-context { + color: #E74C3C +} + +.wy-inline-validate.wy-inline-validate-warning .wy-input-context { + color: #E67E22 +} + +.wy-inline-validate.wy-inline-validate-info .wy-input-context { + color: #2980B9 +} + +.rotate-90 { + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg) +} + +.rotate-180 { + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg) +} + +.rotate-270 { + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg) +} + +.mirror { + -webkit-transform: scaleX(-1); + -moz-transform: scaleX(-1); + -ms-transform: scaleX(-1); + -o-transform: scaleX(-1); + transform: scaleX(-1) +} + +.mirror.rotate-90 { + -webkit-transform: scaleX(-1) rotate(90deg); + -moz-transform: scaleX(-1) rotate(90deg); + -ms-transform: scaleX(-1) rotate(90deg); + -o-transform: scaleX(-1) rotate(90deg); + transform: scaleX(-1) rotate(90deg) +} + +.mirror.rotate-180 { + -webkit-transform: scaleX(-1) rotate(180deg); + -moz-transform: scaleX(-1) rotate(180deg); + -ms-transform: scaleX(-1) rotate(180deg); + -o-transform: scaleX(-1) rotate(180deg); + transform: scaleX(-1) rotate(180deg) +} + +.mirror.rotate-270 { + -webkit-transform: scaleX(-1) rotate(270deg); + -moz-transform: scaleX(-1) rotate(270deg); + -ms-transform: scaleX(-1) rotate(270deg); + -o-transform: scaleX(-1) rotate(270deg); + transform: scaleX(-1) rotate(270deg) +} + +@media only screen and (max-width: 480px) { + .wy-form button[type="submit"] { + margin: 0.7em 0 0 + } + + .wy-form input[type="text"], .wy-form input[type="password"], .wy-form input[type="email"], .wy-form input[type="url"], .wy-form input[type="date"], .wy-form input[type="month"], .wy-form input[type="time"], .wy-form input[type="datetime"], .wy-form input[type="datetime-local"], .wy-form input[type="week"], .wy-form input[type="number"], .wy-form input[type="search"], .wy-form input[type="tel"], .wy-form input[type="color"] { + margin-bottom: 0.3em; + display: block + } + + .wy-form label { + margin-bottom: 0.3em; + display: block + } + + .wy-form input[type="password"], .wy-form input[type="email"], .wy-form input[type="url"], .wy-form input[type="date"], .wy-form input[type="month"], .wy-form input[type="time"], .wy-form input[type="datetime"], .wy-form input[type="datetime-local"], .wy-form input[type="week"], .wy-form input[type="number"], .wy-form input[type="search"], .wy-form input[type="tel"], .wy-form input[type="color"] { + margin-bottom: 0 + } + + .wy-form-aligned .wy-control-group label { + margin-bottom: 0.3em; + text-align: left; + display: block; + width: 100% + } + + .wy-form-aligned .wy-control { + margin: 1.5em 0 0 0 + } + + .wy-form .wy-help-inline, .wy-form-message-inline, .wy-form-message { + display: block; + font-size: 80%; + padding: 6px 0 + } +} + +@media screen and (max-width: 768px) { + .tablet-hide { + display: none + } +} + +@media screen and (max-width: 480px) { + .mobile-hide { + display: none + } +} + +.float-left { + float: left +} + +.float-right { + float: right +} + +.full-width { + width: 100% +} + +.wy-table, .rst-content table.docutils, .rst-content table.field-list { + border-collapse: collapse; + border-spacing: 0; + empty-cells: show; + margin-bottom: 24px +} + +.wy-table caption, .rst-content table.docutils caption, .rst-content table.field-list caption { + color: #000; + font: italic 85%/1 arial, sans-serif; + padding: 1em 0; + text-align: center +} + +.wy-table td, .rst-content table.docutils td, .rst-content table.field-list td, .wy-table th, .rst-content table.docutils th, .rst-content table.field-list th { + font-size: 90%; + margin: 0; + overflow: visible; + padding: 8px 16px +} + +.wy-table td:first-child, .rst-content table.docutils td:first-child, .rst-content table.field-list td:first-child, .wy-table th:first-child, .rst-content table.docutils th:first-child, .rst-content table.field-list th:first-child { + border-left-width: 0 +} + +.wy-table thead, .rst-content table.docutils thead, .rst-content table.field-list thead { + color: #000; + text-align: left; + vertical-align: bottom; + white-space: nowrap +} + +.wy-table thead th, .rst-content table.docutils thead th, .rst-content table.field-list thead th { + font-weight: bold; + border-bottom: solid 2px #e1e4e5 +} + +.wy-table td, .rst-content table.docutils td, .rst-content table.field-list td { + background-color: transparent; + vertical-align: middle +} + +.wy-table td p, .rst-content table.docutils td p, .rst-content table.field-list td p { + line-height: 18px +} + +.wy-table td p:last-child, .rst-content table.docutils td p:last-child, .rst-content table.field-list td p:last-child { + margin-bottom: 0 +} + +.wy-table .wy-table-cell-min, .rst-content table.docutils .wy-table-cell-min, .rst-content table.field-list .wy-table-cell-min { + width: 1%; + padding-right: 0 +} + +.wy-table .wy-table-cell-min input[type=checkbox], .rst-content table.docutils .wy-table-cell-min input[type=checkbox], .rst-content table.field-list .wy-table-cell-min input[type=checkbox], .wy-table .wy-table-cell-min input[type=checkbox], .rst-content table.docutils .wy-table-cell-min input[type=checkbox], .rst-content table.field-list .wy-table-cell-min input[type=checkbox] { + margin: 0 +} + +.wy-table-secondary { + color: gray; + font-size: 90% +} + +.wy-table-tertiary { + color: gray; + font-size: 80% +} + +.wy-table-odd td, .wy-table-striped tr:nth-child(2n-1) td, .rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td { + background-color: #f3f6f6 +} + +.wy-table-backed { + background-color: #f3f6f6 +} + +.wy-table-bordered-all, .rst-content table.docutils { + border: 1px solid #e1e4e5 +} + +.wy-table-bordered-all td, .rst-content table.docutils td { + border-bottom: 1px solid #e1e4e5; + border-left: 1px solid #e1e4e5 +} + +.wy-table-bordered-all tbody > tr:last-child td, .rst-content table.docutils tbody > tr:last-child td { + border-bottom-width: 0 +} + +.wy-table-bordered { + border: 1px solid #e1e4e5 +} + +.wy-table-bordered-rows td { + border-bottom: 1px solid #e1e4e5 +} + +.wy-table-bordered-rows tbody > tr:last-child td { + border-bottom-width: 0 +} + +.wy-table-horizontal tbody > tr:last-child td { + border-bottom-width: 0 +} + +.wy-table-horizontal td, .wy-table-horizontal th { + border-width: 0 0 1px 0; + border-bottom: 1px solid #e1e4e5 +} + +.wy-table-horizontal tbody > tr:last-child td { + border-bottom-width: 0 +} + +.wy-table-responsive { + margin-bottom: 24px; + max-width: 100%; + overflow: auto +} + +.wy-table-responsive table { + margin-bottom: 0 !important +} + +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: nowrap +} + +a { + color: #2980B9; + text-decoration: none; + cursor: pointer +} + +a:hover { + color: #3091d1 +} + +a:visited { + color: #9B59B6 +} + +html { + height: 100%; + overflow-x: hidden +} + +body { + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + font-weight: normal; + color: #404040; + min-height: 100%; + overflow-x: hidden; + background: #edf0f2 +} + +.wy-text-left { + text-align: left +} + +.wy-text-center { + text-align: center +} + +.wy-text-right { + text-align: right +} + +.wy-text-large { + font-size: 120% +} + +.wy-text-normal { + font-size: 100% +} + +.wy-text-small, small { + font-size: 80% +} + +.wy-text-strike { + text-decoration: line-through +} + +.wy-text-warning { + color: #E67E22 !important +} + +a.wy-text-warning:hover { + color: #eb9950 !important +} + +.wy-text-info { + color: #2980B9 !important +} + +a.wy-text-info:hover { + color: #409ad5 !important +} + +.wy-text-success { + color: #27AE60 !important +} + +a.wy-text-success:hover { + color: #36d278 !important +} + +.wy-text-danger { + color: #E74C3C !important +} + +a.wy-text-danger:hover { + color: #ed7669 !important +} + +.wy-text-neutral { + color: #404040 !important +} + +a.wy-text-neutral:hover { + color: #595959 !important +} + +h1, h2, .rst-content .toctree-wrapper p.caption, h3, h4, h5, h6, legend { + margin-top: 0; + font-weight: 700; + font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif +} + +p { + line-height: 24px; + margin: 0; + font-size: 16px; + margin-bottom: 24px +} + +h1 { + font-size: 175% +} + +h2, .rst-content .toctree-wrapper p.caption { + font-size: 150% +} + +h3 { + font-size: 125% +} + +h4 { + font-size: 115% +} + +h5 { + font-size: 110% +} + +h6 { + font-size: 100% +} + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #e1e4e5; + margin: 24px 0; + padding: 0 +} + +code, .rst-content tt, .rst-content code { + white-space: nowrap; + max-width: 100%; + background: #fff; + border: solid 1px #e1e4e5; + font-size: 75%; + padding: 0 5px; + font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; + color: #E74C3C; + overflow-x: auto +} + +code.code-large, .rst-content tt.code-large { + font-size: 90% +} + +.wy-plain-list-disc, .rst-content .section ul, .rst-content .toctree-wrapper ul, article ul { + list-style: disc; + line-height: 24px; + margin-bottom: 24px +} + +.wy-plain-list-disc li, .rst-content .section ul li, .rst-content .toctree-wrapper ul li, article ul li { + list-style: disc; + margin-left: 24px +} + +.wy-plain-list-disc li p:last-child, .rst-content .section ul li p:last-child, .rst-content .toctree-wrapper ul li p:last-child, article ul li p:last-child { + margin-bottom: 0 +} + +.wy-plain-list-disc li ul, .rst-content .section ul li ul, .rst-content .toctree-wrapper ul li ul, article ul li ul { + margin-bottom: 0 +} + +.wy-plain-list-disc li li, .rst-content .section ul li li, .rst-content .toctree-wrapper ul li li, article ul li li { + list-style: circle +} + +.wy-plain-list-disc li li li, .rst-content .section ul li li li, .rst-content .toctree-wrapper ul li li li, article ul li li li { + list-style: square +} + +.wy-plain-list-disc li ol li, .rst-content .section ul li ol li, .rst-content .toctree-wrapper ul li ol li, article ul li ol li { + list-style: decimal +} + +.wy-plain-list-decimal, .rst-content .section ol, .rst-content ol.arabic, article ol { + list-style: decimal; + line-height: 24px; + margin-bottom: 24px +} + +.wy-plain-list-decimal li, .rst-content .section ol li, .rst-content ol.arabic li, article ol li { + list-style: decimal; + margin-left: 24px +} + +.wy-plain-list-decimal li p:last-child, .rst-content .section ol li p:last-child, .rst-content ol.arabic li p:last-child, article ol li p:last-child { + margin-bottom: 0 +} + +.wy-plain-list-decimal li ul, .rst-content .section ol li ul, .rst-content ol.arabic li ul, article ol li ul { + margin-bottom: 0 +} + +.wy-plain-list-decimal li ul li, .rst-content .section ol li ul li, .rst-content ol.arabic li ul li, article ol li ul li { + list-style: disc +} + +.codeblock-example { + border: 1px solid #e1e4e5; + border-bottom: none; + padding: 24px; + padding-top: 48px; + font-weight: 500; + background: #fff; + position: relative +} + +.codeblock-example:after { + content: "Example"; + position: absolute; + top: 0px; + left: 0px; + background: #9B59B6; + color: #fff; + padding: 6px 12px +} + +.codeblock-example.prettyprint-example-only { + border: 1px solid #e1e4e5; + margin-bottom: 24px +} + +.codeblock, pre.literal-block, .rst-content .literal-block, .rst-content pre.literal-block, div[class^='highlight'] { + border: 1px solid #e1e4e5; + padding: 0px; + overflow-x: auto; + background: #fff; + margin: 1px 0 24px 0 +} + +.codeblock div[class^='highlight'], pre.literal-block div[class^='highlight'], .rst-content .literal-block div[class^='highlight'], div[class^='highlight'] div[class^='highlight'] { + border: none; + background: none; + margin: 0 +} + +div[class^='highlight'] td.code { + width: 100% +} + +.linenodiv pre { + border-right: solid 1px #e6e9ea; + margin: 0; + padding: 12px 12px; + font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; + font-size: 12px; + line-height: 1.5; + color: #d9d9d9 +} + +div[class^='highlight'] pre { + white-space: pre; + margin: 0; + padding: 12px 12px; + font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; + font-size: 12px; + line-height: 1.5; + display: block; + overflow: auto; + color: #404040 +} + +@media print { + .codeblock, pre.literal-block, .rst-content .literal-block, .rst-content pre.literal-block, div[class^='highlight'], div[class^='highlight'] pre { + white-space: pre-wrap + } +} + +.hll { + background-color: #ffc; + margin: 0 -12px; + padding: 0 12px; + display: block +} + +.c { + color: #998; + font-style: italic +} + +.err { + color: #a61717; + background-color: #e3d2d2 +} + +.k { + font-weight: bold +} + +.o { + font-weight: bold +} + +.cm { + color: #998; + font-style: italic +} + +.cp { + color: #999; + font-weight: bold +} + +.c1 { + color: #998; + font-style: italic +} + +.cs { + color: #999; + font-weight: bold; + font-style: italic +} + +.gd { + color: #000; + background-color: #fdd +} + +.gd .x { + color: #000; + background-color: #faa +} + +.ge { + font-style: italic +} + +.gr { + color: #a00 +} + +.gh { + color: #999 +} + +.gi { + color: #000; + background-color: #dfd +} + +.gi .x { + color: #000; + background-color: #afa +} + +.go { + color: #888 +} + +.gp { + color: #555 +} + +.gs { + font-weight: bold +} + +.gu { + color: purple; + font-weight: bold +} + +.gt { + color: #a00 +} + +.kc { + font-weight: bold +} + +.kd { + font-weight: bold +} + +.kn { + font-weight: bold +} + +.kp { + font-weight: bold +} + +.kr { + font-weight: bold +} + +.kt { + color: #458; + font-weight: bold +} + +.m { + color: #099 +} + +.s { + color: #d14 +} + +.n { + color: #333 +} + +.na { + color: teal +} + +.nb { + color: #0086b3 +} + +.nc { + color: #458; + font-weight: bold +} + +.no { + color: teal +} + +.ni { + color: purple +} + +.ne { + color: #900; + font-weight: bold +} + +.nf { + color: #900; + font-weight: bold +} + +.nn { + color: #555 +} + +.nt { + color: navy +} + +.nv { + color: teal +} + +.ow { + font-weight: bold +} + +.w { + color: #bbb +} + +.mf { + color: #099 +} + +.mh { + color: #099 +} + +.mi { + color: #099 +} + +.mo { + color: #099 +} + +.sb { + color: #d14 +} + +.sc { + color: #d14 +} + +.sd { + color: #d14 +} + +.s2 { + color: #d14 +} + +.se { + color: #d14 +} + +.sh { + color: #d14 +} + +.si { + color: #d14 +} + +.sx { + color: #d14 +} + +.sr { + color: #009926 +} + +.s1 { + color: #d14 +} + +.ss { + color: #990073 +} + +.bp { + color: #999 +} + +.vc { + color: teal +} + +.vg { + color: teal +} + +.vi { + color: teal +} + +.il { + color: #099 +} + +.gc { + color: #999; + background-color: #EAF2F5 +} + +.wy-breadcrumbs li { + display: inline-block +} + +.wy-breadcrumbs li.wy-breadcrumbs-aside { + float: right +} + +.wy-breadcrumbs li a { + display: inline-block; + padding: 5px +} + +.wy-breadcrumbs li a:first-child { + padding-left: 0 +} + +.wy-breadcrumbs li code, .wy-breadcrumbs li .rst-content tt, .rst-content .wy-breadcrumbs li tt { + padding: 5px; + border: none; + background: none +} + +.wy-breadcrumbs li code.literal, .wy-breadcrumbs li .rst-content tt.literal, .rst-content .wy-breadcrumbs li tt.literal { + color: #404040 +} + +.wy-breadcrumbs-extra { + margin-bottom: 0; + color: #b3b3b3; + font-size: 80%; + display: inline-block +} + +@media screen and (max-width: 480px) { + .wy-breadcrumbs-extra { + display: none + } + + .wy-breadcrumbs li.wy-breadcrumbs-aside { + display: none + } +} + +@media print { + .wy-breadcrumbs li.wy-breadcrumbs-aside { + display: none + } +} + +.wy-affix { + position: fixed; + top: 1.618em +} + +.wy-menu a:hover { + text-decoration: none +} + +.wy-menu-horiz { + *zoom: 1 +} + +.wy-menu-horiz:before, .wy-menu-horiz:after { + display: table; + content: "" +} + +.wy-menu-horiz:after { + clear: both +} + +.wy-menu-horiz ul, .wy-menu-horiz li { + display: inline-block +} + +.wy-menu-horiz li:hover { + background: rgba(255, 255, 255, 0.1) +} + +.wy-menu-horiz li.divide-left { + border-left: solid 1px #404040 +} + +.wy-menu-horiz li.divide-right { + border-right: solid 1px #404040 +} + +.wy-menu-horiz a { + height: 32px; + display: inline-block; + line-height: 32px; + padding: 0 16px +} + +.wy-menu-vertical header, .wy-menu-vertical p.caption { + height: 32px; + display: inline-block; + line-height: 32px; + padding: 0 1.618em; + margin-bottom: 0; + display: block; + font-weight: bold; + text-transform: uppercase; + font-size: 80%; + color: #555; + white-space: nowrap +} + +.wy-menu-vertical ul { + margin-bottom: 0 +} + +.wy-menu-vertical li.divide-top { + border-top: solid 1px #404040 +} + +.wy-menu-vertical li.divide-bottom { + border-bottom: solid 1px #404040 +} + +.wy-menu-vertical li.current { + background: #e3e3e3 +} + +.wy-menu-vertical li.current a { + color: gray; + border-right: solid 1px #c9c9c9; + padding: 0.4045em 2.427em +} + +.wy-menu-vertical li.current a:hover { + background: #d6d6d6 +} + +.wy-menu-vertical li code, .wy-menu-vertical li .rst-content tt, .rst-content .wy-menu-vertical li tt { + border: none; + background: inherit; + color: inherit; + padding-left: 0; + padding-right: 0 +} + +.wy-menu-vertical li span.toctree-expand { + display: block; + float: left; + margin-left: -1.2em; + font-size: 0.8em; + line-height: 1.6em; + color: #4d4d4d +} + +.wy-menu-vertical li.on a, .wy-menu-vertical li.current > a { + color: #404040; + padding: 0.4045em 1.618em; + font-weight: bold; + position: relative; + background: #fcfcfc; + border: none; + border-bottom: solid 1px #c9c9c9; + border-top: solid 1px #c9c9c9; + padding-left: 1.618em -4px +} + +.wy-menu-vertical li.on a:hover, .wy-menu-vertical li.current > a:hover { + background: #fcfcfc +} + +.wy-menu-vertical li.on a:hover span.toctree-expand, .wy-menu-vertical li.current > a:hover span.toctree-expand { + color: gray +} + +.wy-menu-vertical li.on a span.toctree-expand, .wy-menu-vertical li.current > a span.toctree-expand { + display: block; + font-size: 0.8em; + line-height: 1.6em; + color: #333 +} + +.wy-menu-vertical li.toctree-l1.current li.toctree-l2 > ul, .wy-menu-vertical li.toctree-l2.current li.toctree-l3 > ul { + display: none +} + +.wy-menu-vertical li.toctree-l1.current li.toctree-l2.current > ul, .wy-menu-vertical li.toctree-l2.current li.toctree-l3.current > ul { + display: block +} + +.wy-menu-vertical li.toctree-l2.current > a { + background: #c9c9c9; + padding: 0.4045em 2.427em +} + +.wy-menu-vertical li.toctree-l2.current li.toctree-l3 > a { + display: block; + background: #c9c9c9; + padding: 0.4045em 4.045em +} + +.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand { + color: gray +} + +.wy-menu-vertical li.toctree-l2 span.toctree-expand { + color: #a3a3a3 +} + +.wy-menu-vertical li.toctree-l3 { + font-size: 0.9em +} + +.wy-menu-vertical li.toctree-l3.current > a { + background: #bdbdbd; + padding: 0.4045em 4.045em +} + +.wy-menu-vertical li.toctree-l3.current li.toctree-l4 > a { + display: block; + background: #bdbdbd; + padding: 0.4045em 5.663em; + border-top: none; + border-bottom: none +} + +.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand { + color: gray +} + +.wy-menu-vertical li.toctree-l3 span.toctree-expand { + color: #969696 +} + +.wy-menu-vertical li.toctree-l4 { + font-size: 0.9em +} + +.wy-menu-vertical li.current ul { + display: block +} + +.wy-menu-vertical li ul { + margin-bottom: 0; + display: none +} + +.wy-menu-vertical .local-toc li ul { + display: block +} + +.wy-menu-vertical li ul li a { + margin-bottom: 0; + color: #b3b3b3; + font-weight: normal +} + +.wy-menu-vertical a { + display: inline-block; + line-height: 18px; + padding: 0.4045em 1.618em; + display: block; + position: relative; + font-size: 90%; + color: #b3b3b3 +} + +.wy-menu-vertical a:hover { + background-color: #4e4a4a; + cursor: pointer +} + +.wy-menu-vertical a:hover span.toctree-expand { + color: #b3b3b3 +} + +.wy-menu-vertical a:active { + background-color: #2980B9; + cursor: pointer; + color: #fff +} + +.wy-menu-vertical a:active span.toctree-expand { + color: #fff +} + +.wy-side-nav-search { + z-index: 200; + background-color: #2980B9; + text-align: center; + padding: 0.809em; + display: block; + color: #fcfcfc; + margin-bottom: 0.809em +} + +.wy-side-nav-search input[type=text] { + width: 100%; + border-radius: 50px; + padding: 6px 12px; + border-color: #2472a4 +} + +.wy-side-nav-search img { + display: block; + margin: auto auto 0.809em auto; + height: 45px; + width: 45px; + background-color: #2980B9; + padding: 5px; + border-radius: 100% +} + +.wy-side-nav-search > a, .wy-side-nav-search .wy-dropdown > a { + color: #fcfcfc; + font-size: 100%; + font-weight: bold; + display: inline-block; + padding: 4px 6px; + margin-bottom: 0.809em +} + +.wy-side-nav-search > a:hover, .wy-side-nav-search .wy-dropdown > a:hover { + background: rgba(255, 255, 255, 0.1) +} + +.wy-side-nav-search > a img.logo, .wy-side-nav-search .wy-dropdown > a img.logo { + display: block; + margin: 0 auto; + height: auto; + width: auto; + border-radius: 0; + max-width: 100%; + background: transparent +} + +.wy-side-nav-search > a.icon img.logo, .wy-side-nav-search .wy-dropdown > a.icon img.logo { + margin-top: 0.85em +} + +.wy-side-nav-search > div.version { + margin-top: -0.4045em; + margin-bottom: 0.809em; + font-weight: normal; + color: rgba(255, 255, 255, 0.3) +} + +.wy-nav .wy-menu-vertical header { + color: #2980B9 +} + +.wy-nav .wy-menu-vertical a { + color: #b3b3b3 +} + +.wy-nav .wy-menu-vertical a:hover { + background-color: #2980B9; + color: #fff +} + +[data-menu-wrap] { + -webkit-transition: all 0.2s ease-in; + -moz-transition: all 0.2s ease-in; + transition: all 0.2s ease-in; + position: absolute; + opacity: 1; + width: 100%; + opacity: 0 +} + +[data-menu-wrap].move-center { + left: 0; + right: auto; + opacity: 1 +} + +[data-menu-wrap].move-left { + right: auto; + left: -100%; + opacity: 0 +} + +[data-menu-wrap].move-right { + right: -100%; + left: auto; + opacity: 0 +} + +.wy-body-for-nav { + background: left repeat-y #fcfcfc; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxOERBMTRGRDBFMUUxMUUzODUwMkJCOThDMEVFNURFMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxOERBMTRGRTBFMUUxMUUzODUwMkJCOThDMEVFNURFMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjE4REExNEZCMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE4REExNEZDMEUxRTExRTM4NTAyQkI5OEMwRUU1REUwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EwrlwAAAAA5JREFUeNpiMDU0BAgwAAE2AJgB9BnaAAAAAElFTkSuQmCC); + background-size: 300px 1px +} + +.wy-grid-for-nav { + position: absolute; + width: 100%; + height: 100% +} + +.wy-nav-side { + position: fixed; + top: 0; + bottom: 0; + left: 0; + padding-bottom: 2em; + width: 300px; + overflow-x: hidden; + overflow-y: scroll; + min-height: 100%; + background: #343131; + z-index: 200 +} + +.wy-nav-top { + display: none; + background: #2980B9; + color: #fff; + padding: 0.4045em 0.809em; + position: relative; + line-height: 50px; + text-align: center; + font-size: 100%; + *zoom: 1 +} + +.wy-nav-top:before, .wy-nav-top:after { + display: table; + content: "" +} + +.wy-nav-top:after { + clear: both +} + +.wy-nav-top a { + color: #fff; + font-weight: bold +} + +.wy-nav-top img { + margin-right: 12px; + height: 45px; + width: 45px; + background-color: #2980B9; + padding: 5px; + border-radius: 100% +} + +.wy-nav-top i { + font-size: 30px; + float: left; + cursor: pointer +} + +.wy-nav-content-wrap { + margin-left: 300px; + background: #fcfcfc; + min-height: 100% +} + +.wy-nav-content { + padding: 1.618em 3.236em; + height: 100%; + max-width: 800px; + margin: auto +} + +.wy-body-mask { + position: fixed; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.2); + display: none; + z-index: 499 +} + +.wy-body-mask.on { + display: block +} + +footer { + color: #999 +} + +footer p { + margin-bottom: 12px +} + +footer span.commit code, footer span.commit .rst-content tt, .rst-content footer span.commit tt { + padding: 0px; + font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; + font-size: 1em; + background: none; + border: none; + color: #999 +} + +.rst-footer-buttons { + *zoom: 1 +} + +.rst-footer-buttons:before, .rst-footer-buttons:after { + display: table; + content: "" +} + +.rst-footer-buttons:after { + clear: both +} + +#search-results .search li { + margin-bottom: 24px; + border-bottom: solid 1px #e1e4e5; + padding-bottom: 24px +} + +#search-results .search li:first-child { + border-top: solid 1px #e1e4e5; + padding-top: 24px +} + +#search-results .search li a { + font-size: 120%; + margin-bottom: 12px; + display: inline-block +} + +#search-results .context { + color: gray; + font-size: 90% +} + +@media screen and (max-width: 768px) { + .wy-body-for-nav { + background: #fcfcfc + } + + .wy-nav-top { + display: block + } + + .wy-nav-side { + left: -300px + } + + .wy-nav-side.shift { + width: 85%; + left: 0 + } + + .wy-nav-content-wrap { + margin-left: 0 + } + + .wy-nav-content-wrap .wy-nav-content { + padding: 1.618em + } + + .wy-nav-content-wrap.shift { + position: fixed; + min-width: 100%; + left: 85%; + top: 0; + height: 100%; + overflow: hidden + } +} + +@media screen and (min-width: 1400px) { + .wy-nav-content-wrap { + background: rgba(0, 0, 0, 0.05) + } + + .wy-nav-content { + margin: 0; + background: #fcfcfc + } +} + +@media print { + .rst-versions, footer, .wy-nav-side { + display: none + } + + .wy-nav-content-wrap { + margin-left: 0 + } +} + +.rst-versions { + position: fixed; + bottom: 0; + left: 0; + width: 300px; + color: #fcfcfc; + background: #1f1d1d; + border-top: solid 10px #343131; + font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif; + z-index: 400 +} + +.rst-versions a { + color: #2980B9; + text-decoration: none +} + +.rst-versions .rst-badge-small { + display: none +} + +.rst-versions .rst-current-version { + padding: 12px; + background-color: #272525; + display: block; + text-align: right; + font-size: 90%; + cursor: pointer; + color: #27AE60; + *zoom: 1 +} + +.rst-versions .rst-current-version:before, .rst-versions .rst-current-version:after { + display: table; + content: "" +} + +.rst-versions .rst-current-version:after { + clear: both +} + +.rst-versions .rst-current-version .fa, .rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand, .wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand, .rst-versions .rst-current-version .rst-content .admonition-title, .rst-content .rst-versions .rst-current-version .admonition-title, .rst-versions .rst-current-version .rst-content h1 .headerlink, .rst-content h1 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h2 .headerlink, .rst-content h2 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h3 .headerlink, .rst-content h3 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h4 .headerlink, .rst-content h4 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h5 .headerlink, .rst-content h5 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content h6 .headerlink, .rst-content h6 .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content dl dt .headerlink, .rst-content dl dt .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content p.caption .headerlink, .rst-content p.caption .rst-versions .rst-current-version .headerlink, .rst-versions .rst-current-version .rst-content tt.download span:first-child, .rst-content tt.download .rst-versions .rst-current-version span:first-child, .rst-versions .rst-current-version .rst-content code.download span:first-child, .rst-content code.download .rst-versions .rst-current-version span:first-child, .rst-versions .rst-current-version .icon { + color: #fcfcfc +} + +.rst-versions .rst-current-version .fa-book, .rst-versions .rst-current-version .icon-book { + float: left +} + +.rst-versions .rst-current-version .icon-book { + float: left +} + +.rst-versions .rst-current-version.rst-out-of-date { + background-color: #E74C3C; + color: #fff +} + +.rst-versions .rst-current-version.rst-active-old-version { + background-color: #F1C40F; + color: #000 +} + +.rst-versions.shift-up .rst-other-versions { + display: block +} + +.rst-versions .rst-other-versions { + font-size: 90%; + padding: 12px; + color: gray; + display: none +} + +.rst-versions .rst-other-versions hr { + display: block; + height: 1px; + border: 0; + margin: 20px 0; + padding: 0; + border-top: solid 1px #413d3d +} + +.rst-versions .rst-other-versions dd { + display: inline-block; + margin: 0 +} + +.rst-versions .rst-other-versions dd a { + display: inline-block; + padding: 6px; + color: #fcfcfc +} + +.rst-versions.rst-badge { + width: auto; + bottom: 20px; + right: 20px; + left: auto; + border: none; + max-width: 300px +} + +.rst-versions.rst-badge .icon-book { + float: none +} + +.rst-versions.rst-badge .fa-book, .rst-versions.rst-badge .icon-book { + float: none +} + +.rst-versions.rst-badge.shift-up .rst-current-version { + text-align: right +} + +.rst-versions.rst-badge.shift-up .rst-current-version .fa-book, .rst-versions.rst-badge.shift-up .rst-current-version .icon-book { + float: left +} + +.rst-versions.rst-badge.shift-up .rst-current-version .icon-book { + float: left +} + +.rst-versions.rst-badge .rst-current-version { + width: auto; + height: 30px; + line-height: 30px; + padding: 0 6px; + display: block; + text-align: center +} + +@media screen and (max-width: 768px) { + .rst-versions { + width: 85%; + display: none + } + + .rst-versions.shift { + display: block + } + + img { + width: 100%; + height: auto + } +} + +.rst-content img { + max-width: 100%; + height: auto !important +} + +.rst-content div.figure { + margin-bottom: 24px +} + +.rst-content div.figure p.caption { + font-style: italic +} + +.rst-content div.figure.align-center { + text-align: center +} + +.rst-content .section > img, .rst-content .section > a > img { + margin-bottom: 24px +} + +.rst-content blockquote { + margin-left: 24px; + line-height: 24px; + margin-bottom: 24px +} + +.rst-content .note .last, .rst-content .attention .last, .rst-content .caution .last, .rst-content .danger .last, .rst-content .error .last, .rst-content .hint .last, .rst-content .important .last, .rst-content .tip .last, .rst-content .warning .last, .rst-content .seealso .last, .rst-content .admonition-todo .last { + margin-bottom: 0 +} + +.rst-content .admonition-title:before { + margin-right: 4px +} + +.rst-content .admonition table { + border-color: rgba(0, 0, 0, 0.1) +} + +.rst-content .admonition table td, .rst-content .admonition table th { + background: transparent !important; + border-color: rgba(0, 0, 0, 0.1) !important +} + +.rst-content .section ol.loweralpha, .rst-content .section ol.loweralpha li { + list-style: lower-alpha +} + +.rst-content .section ol.upperalpha, .rst-content .section ol.upperalpha li { + list-style: upper-alpha +} + +.rst-content .section ol p, .rst-content .section ul p { + margin-bottom: 12px +} + +.rst-content .line-block { + margin-left: 24px +} + +.rst-content .topic-title { + font-weight: bold; + margin-bottom: 12px +} + +.rst-content .toc-backref { + color: #404040 +} + +.rst-content .align-right { + float: right; + margin: 0px 0px 24px 24px +} + +.rst-content .align-left { + float: left; + margin: 0px 24px 24px 0px +} + +.rst-content .align-center { + margin: auto; + display: block +} + +.rst-content h1 .headerlink, .rst-content h2 .headerlink, .rst-content .toctree-wrapper p.caption .headerlink, .rst-content h3 .headerlink, .rst-content h4 .headerlink, .rst-content h5 .headerlink, .rst-content h6 .headerlink, .rst-content dl dt .headerlink, .rst-content p.caption .headerlink { + display: none; + visibility: hidden; + font-size: 14px +} + +.rst-content h1 .headerlink:after, .rst-content h2 .headerlink:after, .rst-content .toctree-wrapper p.caption .headerlink:after, .rst-content h3 .headerlink:after, .rst-content h4 .headerlink:after, .rst-content h5 .headerlink:after, .rst-content h6 .headerlink:after, .rst-content dl dt .headerlink:after, .rst-content p.caption .headerlink:after { + visibility: visible; + content: ""; + font-family: FontAwesome; + display: inline-block +} + +.rst-content h1:hover .headerlink, .rst-content h2:hover .headerlink, .rst-content .toctree-wrapper p.caption:hover .headerlink, .rst-content h3:hover .headerlink, .rst-content h4:hover .headerlink, .rst-content h5:hover .headerlink, .rst-content h6:hover .headerlink, .rst-content dl dt:hover .headerlink, .rst-content p.caption:hover .headerlink { + display: inline-block +} + +.rst-content .sidebar { + float: right; + width: 40%; + display: block; + margin: 0 0 24px 24px; + padding: 24px; + background: #f3f6f6; + border: solid 1px #e1e4e5 +} + +.rst-content .sidebar p, .rst-content .sidebar ul, .rst-content .sidebar dl { + font-size: 90% +} + +.rst-content .sidebar .last { + margin-bottom: 0 +} + +.rst-content .sidebar .sidebar-title { + display: block; + font-family: "Roboto Slab", "ff-tisa-web-pro", "Georgia", Arial, sans-serif; + font-weight: bold; + background: #e1e4e5; + padding: 6px 12px; + margin: -24px; + margin-bottom: 24px; + font-size: 100% +} + +.rst-content .highlighted { + background: #F1C40F; + display: inline-block; + font-weight: bold; + padding: 0 6px +} + +.rst-content .footnote-reference, .rst-content .citation-reference { + vertical-align: super; + font-size: 90% +} + +.rst-content table.docutils.citation, .rst-content table.docutils.footnote { + background: none; + border: none; + color: #999 +} + +.rst-content table.docutils.citation td, .rst-content table.docutils.citation tr, .rst-content table.docutils.footnote td, .rst-content table.docutils.footnote tr { + border: none; + background-color: transparent !important; + white-space: normal +} + +.rst-content table.docutils.citation td.label, .rst-content table.docutils.footnote td.label { + padding-left: 0; + padding-right: 0; + vertical-align: top +} + +.rst-content table.docutils.citation tt, .rst-content table.docutils.citation code, .rst-content table.docutils.footnote tt, .rst-content table.docutils.footnote code { + color: #555 +} + +.rst-content table.field-list { + border: none +} + +.rst-content table.field-list td { + border: none; + padding-top: 5px +} + +.rst-content table.field-list td > strong { + display: inline-block; + margin-top: 3px +} + +.rst-content table.field-list .field-name { + padding-right: 10px; + text-align: left; + white-space: nowrap +} + +.rst-content table.field-list .field-body { + text-align: left; + padding-left: 0 +} + +.rst-content tt, .rst-content tt, .rst-content code { + color: #000 +} + +.rst-content tt big, .rst-content tt em, .rst-content tt big, .rst-content code big, .rst-content tt em, .rst-content code em { + font-size: 100% !important; + line-height: normal +} + +.rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal { + color: #E74C3C +} + +.rst-content tt.xref, a .rst-content tt, .rst-content tt.xref, .rst-content code.xref, a .rst-content tt, a .rst-content code { + font-weight: bold; + color: #404040 +} + +.rst-content a tt, .rst-content a tt, .rst-content a code { + color: #2980B9 +} + +.rst-content dl { + margin-bottom: 24px +} + +.rst-content dl dt { + font-weight: bold +} + +.rst-content dl p, .rst-content dl table, .rst-content dl ul, .rst-content dl ol { + margin-bottom: 12px !important +} + +.rst-content dl dd { + margin: 0 0 12px 24px +} + +.rst-content dl:not(.docutils) { + margin-bottom: 24px +} + +.rst-content dl:not(.docutils) dt { + display: inline-block; + margin: 6px 0; + font-size: 90%; + line-height: normal; + background: #e7f2fa; + color: #2980B9; + border-top: solid 3px #6ab0de; + padding: 6px; + position: relative +} + +.rst-content dl:not(.docutils) dt:before { + color: #6ab0de +} + +.rst-content dl:not(.docutils) dt .headerlink { + color: #404040; + font-size: 100% !important +} + +.rst-content dl:not(.docutils) dl dt { + margin-bottom: 6px; + border: none; + border-left: solid 3px #ccc; + background: #f0f0f0; + color: gray +} + +.rst-content dl:not(.docutils) dl dt .headerlink { + color: #404040; + font-size: 100% !important +} + +.rst-content dl:not(.docutils) dt:first-child { + margin-top: 0 +} + +.rst-content dl:not(.docutils) tt, .rst-content dl:not(.docutils) tt, .rst-content dl:not(.docutils) code { + font-weight: bold +} + +.rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) tt.descclassname, .rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) code.descname, .rst-content dl:not(.docutils) tt.descclassname, .rst-content dl:not(.docutils) code.descclassname { + background-color: transparent; + border: none; + padding: 0; + font-size: 100% !important +} + +.rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) tt.descname, .rst-content dl:not(.docutils) code.descname { + font-weight: bold +} + +.rst-content dl:not(.docutils) .optional { + display: inline-block; + padding: 0 4px; + color: #000; + font-weight: bold +} + +.rst-content dl:not(.docutils) .property { + display: inline-block; + padding-right: 8px +} + +.rst-content .viewcode-link, .rst-content .viewcode-back { + display: inline-block; + color: #27AE60; + font-size: 80%; + padding-left: 24px +} + +.rst-content .viewcode-back { + display: block; + float: right +} + +.rst-content p.rubric { + margin-bottom: 12px; + font-weight: bold +} + +.rst-content tt.download, .rst-content code.download { + background: inherit; + padding: inherit; + font-family: inherit; + font-size: inherit; + color: inherit; + border: inherit; + white-space: inherit +} + +.rst-content tt.download span:first-child:before, .rst-content code.download span:first-child:before { + margin-right: 4px +} + +@media screen and (max-width: 480px) { + .rst-content .sidebar { + width: 100% + } +} + +span[id*='MathJax-Span'] { + color: #404040 +} + +.math { + text-align: center +} + +@font-face { + font-family: "Inconsolata"; + font-style: normal; + font-weight: 400; + src: local("Inconsolata"), url(../fonts/Inconsolata.ttf) format("truetype") +} + +@font-face { + font-family: "Inconsolata"; + font-style: normal; + font-weight: 700; + src: local("Inconsolata Bold"), local("Inconsolata-Bold"), url(../fonts/Inconsolata-Bold.ttf) format("truetype") +} + +@font-face { + font-family: "Lato"; + font-style: normal; + font-weight: 400; + src: local("Lato Regular"), local("Lato-Regular"), url(../fonts/Lato-Regular.ttf) format("truetype") +} + +@font-face { + font-family: "Lato"; + font-style: normal; + font-weight: 700; + src: local("Lato Bold"), local("Lato-Bold"), url(../fonts/Lato-Bold.ttf) format("truetype") +} + +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 400; + src: local("Roboto Slab Regular"), local("RobotoSlab-Regular"), url(../fonts/RobotoSlab-Regular.ttf) format("truetype") +} + +@font-face { + font-family: "Roboto Slab"; + font-style: normal; + font-weight: 700; + src: local("Roboto Slab Bold"), local("RobotoSlab-Bold"), url(../fonts/RobotoSlab-Bold.ttf) format("truetype") +} + +/*# sourceMappingURL=theme.css.map */ + +/* Start - Usergrid Additions */ + +.usergrid-table, docutils { + border: 1px solid grey; + margin-bottom: 2em; +} + +.usergrid-30 { + width:30%; +} + +.usergrid-table tr td { + padding: 0.5em; + border: 1px solid grey; + font-size: 80%; +} + +.usergrid-table th, .docutils th { + background-color: #e5ebeb; +} + +.caption-text { + font-size:140%; +} + +tr.ug-even td { + background-color: #EAF2F5; +} + +h2.usergrid-GET-heading { + color: white; + background-color: dodgerblue; +} +h2.usergrid-POST-heading { + color: white; + background-color: green; +} +h2.usergrid-PUT-heading { + color: white; + background-color: orange; +} +h2.usergrid-DELETE-heading { + color: white; + background-color: red; +} + +.rst-footer-buttons { + margin-bottom: 2em; +} + +div.wy-menu-vertical li { + font-size: 15px; + margin-bottom: 0.0em; + margin-left: 1.5em; +} + +ul.simple li, ol.simple li { + font-size: 16px; + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +h1 p { + font-size:150%; +} + +/* End - Usergrid Additions */ + diff --git a/content/docs/_static/css/theme.css.map b/content/docs/_static/css/theme.css.map new file mode 100644 index 0000000000..2ee14e0531 --- /dev/null +++ b/content/docs/_static/css/theme.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "CACE,AAAE,ECQI,iBAAoB,EDPJ,SAAU,ECY1B,cAAiB,EDZD,SAAU,EC2B1B,SAAY,ED3BI,SAAU,EEFlC,uEAAiF,EAC/E,MAAO,EAAE,IAAK,EAEhB,iBAAoB,EAClB,MAAO,EAAE,WAAY,EACrB,OAAQ,EAAE,KAAM,EAChB,IAAK,EAAE,AAAC,EAEV,oBAAqB,EACnB,MAAO,EAAE,GAAI,EAEf,OAAQ,EACN,MAAO,EAAE,GAAI,EAEf,AAAC,EDLO,iBAAoB,ECMd,SAAU,EDDhB,cAAiB,ECCX,SAAU,EDchB,SAAY,ECdN,SAAU,EAExB,GAAI,EACF,QAAS,EAAE,GAAI,EACf,uBAAwB,EAAE,GAAI,EAC9B,mBAAoB,EAAE,GAAI,EAE5B,GAAI,EACF,KAAM,EAAE,AAAC,EAEX,eAAiB,EACf,MAAO,EAAE,AAAC,EAEZ,UAAW,EACT,YAAa,EAAE,SAAU,EAE3B,OAAS,EACP,UAAW,EAAE,GAAI,EAEnB,SAAU,EACR,KAAM,EAAE,AAAC,EAEX,EAAG,EACD,SAAU,EAAE,KAAM,EAGpB,EAAG,EACD,SAAU,EAAE,GAAI,EAChB,IAAK,EAAE,GAAI,EACX,cAAe,EAAE,GAAI,EAEvB,GAAI,EACF,SAAU,EAAE,GAAI,EAChB,IAAK,EAAE,GAAI,EACX,SAAU,EAAE,KAAM,EAClB,UAAW,EAAE,GAAI,EAEnB,kDAAoB,EAClB,UAAW,EAAE,cAAS,EACtB,WAAY,EAAE,sBAAa,EAC3B,QAAS,EAAE,EAAG,EAEhB,EAAG,EACD,UAAW,EAAE,EAAG,EAElB,AAAC,EACC,KAAM,EAAE,GAAI,EAEd,eAAiB,EACf,MAAO,EAAE,CAAE,EACX,MAAO,EAAE,GAAI,EAEf,IAAK,EACH,QAAS,EAAE,EAAG,EAEhB,MAAQ,EACN,QAAS,EAAE,EAAG,EACd,UAAW,EAAE,AAAC,EACd,OAAQ,EAAE,OAAQ,EAClB,aAAc,EAAE,OAAQ,EAE1B,EAAG,EACD,EAAG,EAAE,KAAM,EAEb,EAAG,EACD,KAAM,EAAE,MAAO,EAEjB,OAAU,EACR,KAAM,EAAE,AAAC,EACT,MAAO,EAAE,AAAC,EACV,SAAU,EAAE,GAAI,EAChB,eAAgB,EAAE,GAAI,EAExB,CAAE,EACA,SAAU,EAAE,GAAI,EAElB,CAAE,EACA,KAAM,EAAE,AAAC,EAEX,EAAG,EACD,KAAM,EAAE,AAAC,EACT,qBAAsB,EAAE,MAAO,EAC/B,aAAc,EAAE,KAAM,EACtB,QAAS,EAAE,GAAI,EAEjB,aAAc,EACZ,OAAQ,EAAE,KAAM,EAElB,KAAM,EACJ,KAAM,EAAE,AAAC,EAEX,GAAI,EACF,KAAM,EAAE,AAAC,EAEX,OAAQ,EACN,KAAM,EAAE,AAAC,EACT,KAAM,EAAE,AAAC,EACT,MAAO,EAAE,AAAC,EAEZ,IAAK,EACH,KAAM,EAAE,MAAO,EAEjB,KAAM,EACJ,KAAM,EAAE,AAAC,EACT,WAAY,EAAE,GAAI,EAClB,MAAO,EAAE,AAAC,EACV,UAAW,EAAE,KAAM,EAErB,2BAA+B,EAC7B,QAAS,EAAE,GAAI,EACf,KAAM,EAAE,AAAC,EACT,aAAc,EAAE,OAAQ,EACxB,cAAe,EAAE,KAAM,EAEzB,WAAa,EACX,UAAW,EAAE,KAAM,EAErB,mEAAuE,EACrE,KAAM,EAAE,MAAO,EACf,iBAAkB,EAAE,KAAM,EAC1B,QAAS,EAAE,MAAO,EAEpB,+BAAiC,EAC/B,KAAM,EAAE,MAAO,EAEjB,yCAA2C,EACzC,SAAU,EAAE,SAAU,EACtB,MAAO,EAAE,AAAC,EACV,KAAM,EAAE,GAAI,EACZ,MAAO,EAAE,GAAI,EAEf,mBAAoB,EAClB,iBAAkB,EAAE,QAAS,EAC7B,cAAe,EAAE,UAAW,EAC5B,iBAAkB,EAAE,UAAW,EAC/B,SAAU,EAAE,UAAW,EAEzB,iGAAmG,EACjG,iBAAkB,EAAE,GAAI,EAE1B,+CAAiD,EAC/C,KAAM,EAAE,AAAC,EACT,MAAO,EAAE,AAAC,EAEZ,OAAQ,EACN,OAAQ,EAAE,GAAI,EACd,aAAc,EAAE,EAAG,EACnB,KAAM,EAAE,OAAQ,EAElB,IAAK,EACH,cAAe,EAAE,OAAQ,EACzB,aAAc,EAAE,AAAC,EAEnB,CAAE,EACA,aAAc,EAAE,EAAG,EAErB,WAAY,EACV,KAAM,EAAE,MAAO,EACf,SAAU,EAAE,GAAI,EAChB,IAAK,EAAE,GAAK,EACZ,MAAO,EAAE,MAAO,EAElB,EAAG,EACD,MAAO,EAAE,IAAK,EACd,KAAM,EAAE,AAAC,EACT,UAAW,EAAE,KAAM,EACnB,OAAQ,EAAE,KAAM,EAChB,eAAgB,EAAE,UAAW,EAC7B,gBAAiB,EAAE,QAAS,EAC5B,SAAU,EAAE,GAAI,EAChB,QAAS,EAAE,EAAG,EACd,WAAY,EAAE,AAAC,EAEjB,KAAM,EACJ,MAAO,EAAE,GAAI,EAEf,MAAO,EACL,MAAO,EAAE,cAAe,EACxB,SAAU,EAAE,KAAM,EAEpB,cAAe,EACb,KAAM,EAAE,AAAC,EACT,GAAI,EAAE,YAAa,EACnB,KAAM,EAAE,EAAG,EACX,KAAM,EAAE,GAAI,EACZ,OAAQ,EAAE,KAAM,EAChB,MAAO,EAAE,AAAC,EACV,OAAQ,EAAE,OAAQ,EAClB,IAAK,EAAE,EAAG,EAEZ,+DAAiE,EAC/D,GAAI,EAAE,GAAI,EACV,KAAM,EAAE,GAAI,EACZ,KAAM,EAAE,AAAC,EACT,OAAQ,EAAE,MAAO,EACjB,OAAQ,EAAE,KAAM,EAChB,IAAK,EAAE,GAAI,EAEb,SAAU,EACR,SAAU,EAAE,KAAM,EAEpB,QAAS,EACP,OAAQ,EAAE,OAAQ,EAEpB,QAAU,EACR,QAAS,EAAE,GAAI,EAEjB,WAAY,EACV,gBAAmB,EACjB,SAAU,EAAE,cAAe,EAC7B,AAAC,EACC,SAAU,EAAE,cAAe,EAC3B,UAAW,EAAE,cAAe,EAC5B,KAAM,EAAE,cAAe,EACvB,SAAU,EAAE,cAAe,EAC7B,UAAY,EACV,cAAe,EAAE,QAAS,EAC5B,0DAA6D,EAC3D,MAAO,EAAE,CAAE,EACb,aAAe,EACb,gBAAiB,EAAE,IAAK,EAC1B,IAAK,EACH,MAAO,EAAE,iBAAkB,EAC7B,KAAO,EACL,gBAAiB,EAAE,IAAK,EAC1B,EAAG,EACD,QAAS,EAAE,cAAe,QAE1B,KAAM,EAAE,IAAK,EAEf,8CAAS,EACP,MAAO,EAAE,AAAC,EACV,KAAM,EAAE,AAAC,EACX,4CAAM,EACJ,eAAgB,EAAE,IAAK,GChM3B,ykDAAY,EACV,qBAAsB,EAAE,UAAW,EAqDrC,QAAS,EARP,IAAK,EAAE,AAAC,EACR,+BAAS,EAEP,MAAO,EAAE,IAAK,EACd,MAAO,EAAE,CAAE,EACb,cAAO,EACL,IAAK,EAAE,GAAI;;;GC1Gf,UAUC,CATC,WAAW,CAAE,aAAa,CAC1B,GAAG,CAAE,+CAAgE,CACrE,GAAG,CAAE,sSAAmG,CAKxG,WAAW,CAAE,MAAM,CACnB,UAAU,CAAE,MAAM,CCTpB,kfAAmB,CACjB,OAAO,CAAE,YAAY,CACrB,IAAI,CAAE,uCAAuC,CAC7C,SAAS,CAAE,OAAO,CAClB,cAAc,CAAE,IAAI,CACpB,sBAAsB,CAAE,WAAW,CACnC,uBAAuB,CAAE,SAAS,CCLpC,MAAsB,CACpB,SAAS,CAAE,SAAS,CACpB,WAAW,CAAE,MAAS,CACtB,cAAc,CAAE,IAAI,CAEtB,MAAsB,CAAE,SAAS,CAAE,GAAG,CACtC,MAAsB,CAAE,SAAS,CAAE,GAAG,CACtC,MAAsB,CAAE,SAAS,CAAE,GAAG,CACtC,MAAsB,CAAE,SAAS,CAAE,GAAG,CCVtC,MAAsB,CACpB,KAAK,CAAE,SAAW,CAClB,UAAU,CAAE,MAAM,CCDpB,MAAsB,CACpB,YAAY,CAAE,CAAC,CACf,WAAW,CCIU,SAAS,CDH9B,eAAe,CAAE,IAAI,CACrB,SAAK,CAAE,QAAQ,CAAE,QAAQ,CAE3B,MAAsB,CACpB,QAAQ,CAAE,QAAQ,CAClB,IAAI,CAAE,UAAa,CACnB,KAAK,CCHgB,SAAS,CDI9B,GAAG,CAAE,SAAU,CACf,UAAU,CAAE,MAAM,CAClB,YAAuB,CACrB,IAAI,CAAE,UAA0B,CEbpC,UAA0B,CACxB,OAAO,CAAE,gBAAgB,CACzB,MAAM,CAAE,iBAA4B,CACpC,aAAa,CAAE,IAAI,CAGrB,WAAY,CAAE,KAAK,CAAE,KAAK,CAC1B,UAAW,CAAE,KAAK,CAAE,IAAI,CAGtB,kpBAAY,CAAE,YAAY,CAAE,IAAI,CAChC,kqBAAa,CAAE,WAAW,CAAE,IAAI,CCXlC,QAAwB,CACtB,iBAAiB,CAAE,0BAA0B,CACrC,SAAS,CAAE,0BAA0B,CAG/C,0BASC,CARC,EAAG,CACD,iBAAiB,CAAE,YAAY,CACvB,SAAS,CAAE,YAAY,CAEjC,IAAK,CACH,iBAAiB,CAAE,cAAc,CACzB,SAAS,CAAE,cAAc,EAIrC,kBASC,CARC,EAAG,CACD,iBAAiB,CAAE,YAAY,CACvB,SAAS,CAAE,YAAY,CAEjC,IAAK,CACH,iBAAiB,CAAE,cAAc,CACzB,SAAS,CAAE,cAAc,ECvBrC,aAA8B,CCU5B,MAAM,CAAE,wDAAmE,CAC3E,iBAAiB,CAAE,aAAgB,CAC/B,aAAa,CAAE,aAAgB,CAC3B,SAAS,CAAE,aAAgB,CDZrC,cAA8B,CCS5B,MAAM,CAAE,wDAAmE,CAC3E,iBAAiB,CAAE,cAAgB,CAC/B,aAAa,CAAE,cAAgB,CAC3B,SAAS,CAAE,cAAgB,CDXrC,cAA8B,CCQ5B,MAAM,CAAE,wDAAmE,CAC3E,iBAAiB,CAAE,cAAgB,CAC/B,aAAa,CAAE,cAAgB,CAC3B,SAAS,CAAE,cAAgB,CDTrC,mBAAmC,CCajC,MAAM,CAAE,wDAAmE,CAC3E,iBAAiB,CAAE,YAAoB,CACnC,aAAa,CAAE,YAAoB,CAC/B,SAAS,CAAE,YAAoB,CDfzC,iBAAmC,CCYjC,MAAM,CAAE,wDAAmE,CAC3E,iBAAiB,CAAE,YAAoB,CACnC,aAAa,CAAE,YAAoB,CAC/B,SAAS,CAAE,YAAoB,CDVzC,+GAIuC,CACrC,MAAM,CAAE,IAAI,CEfd,SAAyB,CACvB,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,YAAY,CACrB,KAAK,CAAE,GAAG,CACV,MAAM,CAAE,GAAG,CACX,WAAW,CAAE,GAAG,CAChB,cAAc,CAAE,MAAM,CAExB,yBAAyD,CACvD,QAAQ,CAAE,QAAQ,CAClB,IAAI,CAAE,CAAC,CACP,KAAK,CAAE,IAAI,CACX,UAAU,CAAE,MAAM,CAEpB,YAA4B,CAAE,WAAW,CAAE,OAAO,CAClD,YAA4B,CAAE,SAAS,CAAE,GAAG,CAC5C,WAA2B,CAAE,KAAK,CLXZ,IAAI,CML1B,gBAAgC,CAAE,OAAO,CNwP1B,GAAO,CMvPtB,gBAAgC,CAAE,OAAO,CNkV1B,GAAO,CMjVtB,qCAAiC,CAAE,OAAO,CNyZ1B,GAAO,CMxZvB,qBAAqC,CAAE,OAAO,CN2K1B,GAAO,CM1K3B,gBAAgC,CAAE,OAAO,CNqQ1B,GAAO,CMpQtB,eAA+B,CAAE,OAAO,CNkc1B,GAAO,CMjcrB,iBAAiC,CAAE,OAAO,CNsc1B,GAAO,CMrcvB,eAA+B,CAAE,OAAO,CN0gB1B,GAAO,CMzgBrB,eAA+B,CAAE,OAAO,CN+M1B,GAAO,CM9MrB,mBAAmC,CAAE,OAAO,CN8d1B,GAAO,CM7dzB,aAA6B,CAAE,OAAO,CN4d1B,GAAO,CM3dnB,kBAAkC,CAAE,OAAO,CN6d1B,GAAO,CM5dxB,gBAAgC,CAAE,OAAO,CN+F1B,GAAO,CM9FtB,mDAEgC,CAAE,OAAO,CNge1B,GAAO,CM/dtB,sBAAsC,CAAE,OAAO,CN6Y1B,GAAO,CM5Y5B,uBAAuC,CAAE,OAAO,CN2Y1B,GAAO,CM1Y7B,oBAAoC,CAAE,OAAO,CNqW1B,GAAO,CMpW1B,iBAAiC,CAAE,OAAO,CNwZ1B,GAAO,CMvZvB,8BAC8B,CAAE,OAAO,CNmH1B,GAAO,CMlHpB,kBAAkC,CAAE,OAAO,CNoe1B,GAAO,CMnexB,iCAA+B,CAAE,OAAO,CNqP1B,GAAO,CMpPrB,iBAAiC,CAAE,OAAO,CNmL1B,GAAO,CMlLvB,kBAAkC,CAAE,OAAO,CNqG1B,GAAO,CMpGxB,eAA+B,CAAE,OAAO,CNqX1B,GAAO,CMpXrB,uHAAmC,CAAE,OAAO,CNyI1B,GAAO,CMxIzB,8BAA8C,CAAE,OAAO,CNG1B,GAAO,CMFpC,4BAA4C,CAAE,OAAO,CNK1B,GAAO,CMJlC,gBAAgC,CAAE,OAAO,CNmP1B,GAAO,CMlPtB,wBAAwC,CAAE,OAAO,CNkV1B,GAAO,CMjV9B,yCACiC,CAAE,OAAO,CNyW1B,GAAO,CMxWvB,kBAAkC,CAAE,OAAO,CNoW1B,GAAO,CMnWxB,mBAAmC,CAAE,OAAO,CNiR1B,GAAO,CMhRzB,eAA+B,CAAE,OAAO,CNoR1B,GAAO,CMnRrB,eAA+B,CAAE,OAAO,CNsL1B,GAAO,CMrLrB,qBAAqC,CAAE,OAAO,CNkO1B,GAAO,CMjO3B,qBAAqC,CAAE,OAAO,CNkf1B,GAAO,CMjf3B,sBAAsC,CAAE,OAAO,CNgf1B,GAAO,CM/e5B,oBAAoC,CAAE,OAAO,CNif1B,GAAO,CMhf1B,iBAAiC,CAAE,OAAO,CNiV1B,GAAO,CMhVvB,kBAAkC,CAAE,OAAO,CNU1B,GAAO,CMTxB,cAA8B,CAAE,OAAO,CNkb1B,GAAO,CMjbpB,eAA+B,CAAE,OAAO,CNkb1B,GAAO,CMjbrB,iCAA+B,CAAE,OAAO,CNyB1B,GAAO,CMxBrB,mBAAmC,CAAE,OAAO,CNyB1B,GAAO,CMxBzB,gBAAgC,CAAE,OAAO,CNwU1B,GAAO,CMvUtB,iBAAiC,CAAE,OAAO,CNqC1B,GAAO,CMpCvB,eAA+B,CAAE,OAAO,CNoL1B,GAAO,CMnLrB,eAA+B,CAAE,OAAO,CNiB1B,GAAO,CMhBrB,iBAAiC,CAAE,OAAO,CNqO1B,GAAO,CMpOvB,sBAAsC,CAAE,OAAO,CN+a1B,GAAO,CM9a5B,qBAAqC,CAAE,OAAO,CN+a1B,GAAO,CM9a3B,qBAAqC,CAAE,OAAO,CN3C1B,GAAO,CM4C3B,uBAAuC,CAAE,OAAO,CN9C1B,GAAO,CM+C7B,sBAAsC,CAAE,OAAO,CN5C1B,GAAO,CM6C5B,wBAAwC,CAAE,OAAO,CN/C1B,GAAO,CMgD9B,eAA+B,CAAE,OAAO,CNwP1B,GAAO,CMvPrB,oCACkC,CAAE,OAAO,CN0R1B,GAAO,CMzRxB,iBAAiC,CAAE,OAAO,CNoN1B,GAAO,CMnNvB,uBAAuC,CAAE,OAAO,CNqd1B,GAAO,CMpd7B,sDAEoC,CAAE,OAAO,CNsS1B,GAAO,CMrS1B,iBAAiC,CAAE,OAAO,CN+R1B,GAAO,CM9RvB,qBAAqC,CAAE,OAAO,CN+P1B,GAAO,CM9P3B,iBAAiC,CAAE,OAAO,CN7D1B,GAAO,CM8DvB,eAA+B,CAAE,OAAO,CN4a1B,GAAO,CM3arB,0CAC0C,CAAE,OAAO,CN4R1B,GAAO,CM3RhC,yBAAyC,CAAE,OAAO,CN2V1B,GAAO,CM1V/B,yBAAyC,CAAE,OAAO,CNqC1B,GAAO,CMpC/B,iBAAiC,CAAE,OAAO,CNlC1B,GAAO,CMmCvB,wBAAwC,CAAE,OAAO,CNmY1B,GAAO,CMlY9B,wBAAwC,CAAE,OAAO,CNkH1B,GAAO,CMjH9B,mBAAmC,CAAE,OAAO,CN9B1B,GAAO,CM+BzB,eAA+B,CAAE,OAAO,CNgS1B,GAAO,CM/RrB,gBAAgC,CAAE,OAAO,CN+Q1B,GAAO,CM9QtB,eAA+B,CAAE,OAAO,CNiY1B,GAAO,CMhYrB,kBAAkC,CAAE,OAAO,CNqJ1B,GAAO,CMpJxB,uBAAuC,CAAE,OAAO,CN6G1B,GAAO,CM5G7B,uBAAuC,CAAE,OAAO,CN4X1B,GAAO,CM3X7B,gBAAgC,CAAE,OAAO,CNoF1B,GAAO,CMnFtB,uBAAuC,CAAE,OAAO,CN+B1B,GAAO,CM9B7B,wBAAwC,CAAE,OAAO,CN+B1B,GAAO,CM9B9B,sBAAsC,CAAE,OAAO,CN4R1B,GAAO,CM3R5B,uBAAuC,CAAE,OAAO,CNkP1B,GAAO,CMjP7B,8FAAuC,CAAE,OAAO,CNsZ1B,GAAO,CMrZ7B,+FAAuC,CAAE,OAAO,CNiB1B,GAAO,CMhB7B,0BAA0C,CAAE,OAAO,CNiS1B,GAAO,CMhShC,sBAAsC,CAAE,OAAO,CNuL1B,GAAO,CMtL5B,qBAAqC,CAAE,OAAO,CNuD1B,GAAO,CMtD3B,yBAAyC,CAAE,OAAO,CNkZ1B,GAAO,CMjZ/B,yBAAyC,CAAE,OAAO,CNa1B,GAAO,CMZ/B,cAA8B,CAAE,OAAO,CNhD1B,GAAO,CMiDpB,qBAAqC,CAAE,OAAO,CN5D1B,GAAO,CM6D3B,sBAAsC,CAAE,OAAO,CN5D1B,GAAO,CM6D5B,mBAAmC,CAAE,OAAO,CN5D1B,GAAO,CM6DzB,qBAAqC,CAAE,OAAO,CNhE1B,GAAO,CMiE3B,wCACgC,CAAE,OAAO,CNyT1B,GAAO,CMxTtB,iBAAiC,CAAE,OAAO,CN+E1B,GAAO,CM9EvB,mBAAmC,CAAE,OAAO,CNuC1B,GAAO,CMtCzB,eAA+B,CAAE,OAAO,CNyQ1B,GAAO,CMxQrB,gBAAgC,CAAE,OAAO,CN+N1B,GAAO,CM9NtB,mBAAmC,CAAE,OAAO,CN/D1B,GAAO,CMgEzB,gNAA6C,CAAE,OAAO,CNwE1B,GAAO,CMvEnC,eAA+B,CAAE,OAAO,CNmI1B,GAAO,CMlIrB,eAA+B,CAAE,OAAO,CNqL1B,GAAO,CMpLrB,iCAA+B,CAAE,OAAO,CNyG1B,GAAO,CMxGrB,cAA8B,CAAE,OAAO,CNyE1B,GAAO,CMxEpB,oBAAoC,CAAE,OAAO,CNyE1B,GAAO,CMxE1B,kDAC+C,CAAE,OAAO,CNkE1B,GAAO,CMjErC,gBAAgC,CAAE,OAAO,CNyP1B,GAAO,CMxPtB,mBAAmC,CAAE,OAAO,CNlC1B,GAAO,CMmCzB,iBAAiC,CAAE,OAAO,CN0Q1B,GAAO,CMzQvB,kBAAkC,CAAE,OAAO,CNmB1B,GAAO,CMlBxB,iBAAiC,CAAE,OAAO,CNqM1B,GAAO,CMpMvB,qBAAqC,CAAE,OAAO,CNH1B,GAAO,CMI3B,uBAAuC,CAAE,OAAO,CNP1B,GAAO,CMQ7B,kBAAkC,CAAE,OAAO,CNiR1B,GAAO,CMhRxB,wBAAwC,CAAE,OAAO,CN2S1B,GAAO,CM1S9B,iBAAiC,CAAE,OAAO,CNoG1B,GAAO,CMnGvB,sBAAsC,CAAE,OAAO,CNqG1B,GAAO,CMpG5B,mBAAmC,CAAE,OAAO,CNpF1B,GAAO,CMqFzB,mBAAmC,CAAE,OAAO,CNtF1B,GAAO,CMuFzB,2CACoC,CAAE,OAAO,CNhF1B,GAAO,CMiF1B,yBAAyC,CAAE,OAAO,CNkY1B,GAAO,CMjY/B,0BAA0C,CAAE,OAAO,CNyD1B,GAAO,CMxDhC,uBAAuC,CAAE,OAAO,CN/C1B,GAAO,CMgD7B,cAA8B,CAAE,OAAO,CNsJ1B,GAAO,CMrJpB,gCAC+B,CAAE,OAAO,CNA1B,GAAO,CMCrB,mBAAmC,CAAE,OAAO,CNG1B,GAAO,CMFzB,sBAAsC,CAAE,OAAO,CNiW1B,GAAO,CMhW5B,wBAAwC,CAAE,OAAO,CN+V1B,GAAO,CM9V9B,oBAAoC,CAAE,OAAO,CN2T1B,GAAO,CM1T1B,kBAAkC,CAAE,OAAO,CN4H1B,GAAO,CM3HxB,mBAAmC,CAAE,OAAO,CN2R1B,GAAO,CM1RzB,0BAA0C,CAAE,OAAO,CNiK1B,GAAO,CMhKhC,qBAAqC,CAAE,OAAO,CNwV1B,GAAO,CMvV3B,wBAAwC,CAAE,OAAO,CNsC1B,GAAO,CMrC9B,kBAAkC,CAAE,OAAO,CNsR1B,GAAO,CMrRxB,iBAAiC,CAAE,OAAO,CNyW1B,GAAO,CMxWvB,wBAAwC,CAAE,OAAO,CNiG1B,GAAO,CMhG9B,iBAAiC,CAAE,OAAO,CNyX1B,GAAO,CMxXvB,kBAAkC,CAAE,OAAO,CN+I1B,GAAO,CM9IxB,gBAAgC,CAAE,OAAO,CN6M1B,GAAO,CM5MtB,mBAAmC,CAAE,OAAO,CN2S1B,GAAO,CM1SzB,qBAAqC,CAAE,OAAO,CNjF1B,GAAO,CMkF3B,uBAAuC,CAAE,OAAO,CN2M1B,GAAO,CM1M7B,kBAAkC,CAAE,OAAO,CNyW1B,GAAO,CMxWxB,mBAAmC,CAAE,OAAO,CNgC1B,GAAO,CM/BzB,qCAAiC,CAAE,OAAO,CNsF1B,GAAO,CMrFvB,iBAAiC,CAAE,OAAO,CN6W1B,GAAO,CM5WvB,sBAAsC,CAAE,OAAO,CNb1B,GAAO,CMc5B,cAA8B,CAAE,OAAO,CNmP1B,GAAO,CMlPpB,gBAAgC,CAAE,OAAO,CNoG1B,GAAO,CMnGtB,mBAAmC,CAAE,OAAO,CNpF1B,GAAO,CMqFzB,eAA+B,CAAE,OAAO,CN1G1B,GAAO,CM2GrB,sBAAsC,CAAE,OAAO,CN7D1B,GAAO,CM8D5B,uBAAuC,CAAE,OAAO,CN8F1B,GAAO,CM7F7B,sBAAsC,CAAE,OAAO,CN4F1B,GAAO,CM3F5B,oBAAoC,CAAE,OAAO,CN6F1B,GAAO,CM5F1B,sBAAsC,CAAE,OAAO,CNyF1B,GAAO,CMxF5B,2DAA4C,CAAE,OAAO,CN5I1B,GAAO,CM6IlC,6DAA6C,CAAE,OAAO,CNxI1B,GAAO,CMyInC,0BAA0C,CAAE,OAAO,CNxI1B,GAAO,CMyIhC,4BAA4C,CAAE,OAAO,CNhJ1B,GAAO,CMiJlC,gBAAgC,CAAE,OAAO,CN2E1B,GAAO,CM1EtB,iBAAiC,CAAE,OAAO,CNqX1B,GAAO,CMpXvB,gBAAgC,CAAE,OAAO,CNgT1B,GAAO,CM/StB,iBAAiC,CAAE,OAAO,CNuC1B,GAAO,CMtCvB,oBAAoC,CAAE,OAAO,CNxG1B,GAAO,CMyG1B,qBAAqC,CAAE,OAAO,CNzI1B,GAAO,CM0I3B,iCACgC,CAAE,OAAO,CN8V1B,GAAO,CM7VtB,kDAC+B,CAAE,OAAO,CNwH1B,GAAO,CMvHrB,gBAAgC,CAAE,OAAO,CNxD1B,GAAO,CMyDtB,gBAAgC,CAAE,OAAO,CNsC1B,GAAO,CMrCtB,kCACmC,CAAE,OAAO,CN+N1B,GAAO,CM9NzB,kCACkC,CAAE,OAAO,CNyB1B,GAAO,CMxBxB,oBAAoC,CAAE,OAAO,CN8J1B,GAAO,CM7J1B,mCACmC,CAAE,OAAO,CNiC1B,GAAO,CMhCzB,iBAAiC,CAAE,OAAO,CNkQ1B,GAAO,CMjQvB,qDAE+B,CAAE,OAAO,CN9I1B,GAAO,CM+IrB,kBAAkC,CAAE,OAAO,CNiH1B,GAAO,CMhHxB,kBAAkC,CAAE,OAAO,CN+G1B,GAAO,CM9GxB,wBAAwC,CAAE,OAAO,CN4Q1B,GAAO,CM3Q9B,oBAAoC,CAAE,OAAO,CNgU1B,GAAO,CM/T1B,gBAAgC,CAAE,OAAO,CNkR1B,GAAO,CMjRtB,gBAAgC,CAAE,OAAO,CNmH1B,GAAO,CMlHtB,gBAAgC,CAAE,OAAO,CNmT1B,GAAO,CMlTtB,oBAAoC,CAAE,OAAO,CNgK1B,GAAO,CM/J1B,2BAA2C,CAAE,OAAO,CNgK1B,GAAO,CM/JjC,6BAA6C,CAAE,OAAO,CN8C1B,GAAO,CM7CnC,sBAAsC,CAAE,OAAO,CN4C1B,GAAO,CM3C5B,gBAAgC,CAAE,OAAO,CNgI1B,GAAO,CM/HtB,wEAAqC,CAAE,OAAO,CNxH1B,GAAO,CMyH3B,mBAAmC,CAAE,OAAO,CNlH1B,GAAO,CMmHzB,qBAAqC,CAAE,OAAO,CNzH1B,GAAO,CM0H3B,sBAAsC,CAAE,OAAO,CNzH1B,GAAO,CM0H5B,kBAAkC,CAAE,OAAO,CN3E1B,GAAO,CM4ExB,mCAC+B,CAAE,OAAO,CN4N1B,GAAO,CM3NrB,yCACoC,CAAE,OAAO,CNgO1B,GAAO,CM/N1B,sCACmC,CAAE,OAAO,CN6N1B,GAAO,CM5NzB,mBAAmC,CAAE,OAAO,CN/C1B,GAAO,CMgDzB,mBAAmC,CAAE,OAAO,CNmF1B,GAAO,CMlFzB,sCAC+B,CAAE,OAAO,CN0S1B,GAAO,CMzSrB,iCACgC,CAAE,OAAO,CNW1B,GAAO,CMVtB,0CACqC,CAAE,OAAO,CN0P1B,GAAO,CMzP3B,oBAAoC,CAAE,OAAO,CNxF1B,GAAO,CMyF1B,qBAAqC,CAAE,OAAO,CNvF1B,GAAO,CMwF3B,gCAC+B,CAAE,OAAO,CNlK1B,GAAO,CMmKrB,kBAAkC,CAAE,OAAO,CNoM1B,GAAO,CMnMxB,mBAAmC,CAAE,OAAO,CN8R1B,GAAO,CM7RzB,qCACoC,CAAE,OAAO,CN9G1B,GAAO,CM+G1B,sBAAsC,CAAE,OAAO,CNiE1B,GAAO,CMhE5B,mBAAmC,CAAE,OAAO,CN1D1B,GAAO,CM2DzB,yBAAyC,CAAE,OAAO,CN7G1B,GAAO,CM8G/B,uBAAuC,CAAE,OAAO,CN7G1B,GAAO,CM8G7B,kBAAkC,CAAE,OAAO,CNkS1B,GAAO,CMjSxB,sBAAsC,CAAE,OAAO,CNgO1B,GAAO,CM/N5B,mBAAmC,CAAE,OAAO,CNqO1B,GAAO,CMpOzB,iBAAiC,CAAE,OAAO,CNxL1B,GAAO,CMyLvB,iBAAiC,CAAE,OAAO,CN7G1B,GAAO,CM8GvB,kBAAkC,CAAE,OAAO,CN3F1B,GAAO,CM4FxB,sBAAsC,CAAE,OAAO,CNpC1B,GAAO,CMqC5B,qBAAqC,CAAE,OAAO,CNzK1B,GAAO,CM0K3B,qBAAqC,CAAE,OAAO,CNqB1B,GAAO,CMpB3B,oBAAoC,CAAE,OAAO,CN3O1B,GAAO,CM4O1B,iBAAiC,CAAE,OAAO,CN4E1B,GAAO,CM3EvB,sBAAsC,CAAE,OAAO,CNxD1B,GAAO,CMyD5B,eAA+B,CAAE,OAAO,CNrM1B,GAAO,CMsMrB,mBAAmC,CAAE,OAAO,CNG1B,GAAO,CMFzB,sBAAsC,CAAE,OAAO,CNuH1B,GAAO,CMtH5B,4BAA4C,CAAE,OAAO,CN5O1B,GAAO,CM6OlC,6BAA6C,CAAE,OAAO,CN5O1B,GAAO,CM6OnC,0BAA0C,CAAE,OAAO,CN5O1B,GAAO,CM6OhC,4BAA4C,CAAE,OAAO,CNhP1B,GAAO,CMiPlC,qBAAqC,CAAE,OAAO,CN5O1B,GAAO,CM6O3B,sBAAsC,CAAE,OAAO,CN5O1B,GAAO,CM6O5B,mBAAmC,CAAE,OAAO,CN5O1B,GAAO,CM6OzB,qBAAqC,CAAE,OAAO,CNhP1B,GAAO,CMiP3B,kBAAkC,CAAE,OAAO,CNxG1B,GAAO,CMyGxB,iBAAiC,CAAE,OAAO,CNyB1B,GAAO,CMxBvB,iBAAiC,CAAE,OAAO,CNmN1B,GAAO,CMlNvB,yCACiC,CAAE,OAAO,CNmE1B,GAAO,CMlEvB,mBAAmC,CAAE,OAAO,CNlJ1B,GAAO,CMmJzB,qBAAqC,CAAE,OAAO,CNiH1B,GAAO,CMhH3B,sBAAsC,CAAE,OAAO,CNiH1B,GAAO,CMhH5B,kBAAkC,CAAE,OAAO,CNiL1B,GAAO,CMhLxB,iBAAiC,CAAE,OAAO,CNvJ1B,GAAO,CMwJvB,sCACgC,CAAE,OAAO,CNyH1B,GAAO,CMxHtB,qBAAqC,CAAE,OAAO,CN9B1B,GAAO,CM+B3B,mBAAmC,CAAE,OAAO,CNjD1B,GAAO,CMkDzB,wBAAwC,CAAE,OAAO,CNhD1B,GAAO,CMiD9B,kBAAkC,CAAE,OAAO,CN2J1B,GAAO,CM1JxB,kBAAkC,CAAE,OAAO,CN9C1B,GAAO,CM+CxB,gBAAgC,CAAE,OAAO,CN+C1B,GAAO,CM9CtB,kBAAkC,CAAE,OAAO,CN9C1B,GAAO,CM+CxB,qBAAqC,CAAE,OAAO,CNI1B,GAAO,CMH3B,iBAAiC,CAAE,OAAO,CN9D1B,GAAO,CM+DvB,yBAAyC,CAAE,OAAO,CNhE1B,GAAO,CMiE/B,mBAAmC,CAAE,OAAO,CNsM1B,GAAO,CMrMzB,eAA+B,CAAE,OAAO,CN1J1B,GAAO,CM2JrB,8CACoC,CAAE,OAAO,CN4G1B,GAAO,CM3G1B,2EAEsC,CAAE,OAAO,CNwK1B,GAAO,CMvK5B,yBAAyC,CAAE,OAAO,CNmB1B,GAAO,CMlB/B,eAA+B,CAAE,OAAO,CNjJ1B,GAAO,CMkJrB,oBAAoC,CAAE,OAAO,CNjK1B,GAAO,CMkK1B,yCACuC,CAAE,OAAO,CN9L1B,GAAO,CM+L7B,mBAAmC,CAAE,OAAO,CNmF1B,GAAO,CMlFzB,eAA+B,CAAE,OAAO,CNvB1B,GAAO,CMwBrB,sBAAsC,CAAE,OAAO,CNvH1B,GAAO,CMwH5B,sBAAsC,CAAE,OAAO,CN6K1B,GAAO,CM5K5B,oBAAoC,CAAE,OAAO,CNyK1B,GAAO,CMxK1B,iBAAiC,CAAE,OAAO,CN9H1B,GAAO,CM+HvB,uBAAuC,CAAE,OAAO,CN0E1B,GAAO,CMzE7B,qBAAqC,CAAE,OAAO,CNwB1B,GAAO,CMvB3B,2BAA2C,CAAE,OAAO,CNwB1B,GAAO,CMvBjC,iBAAiC,CAAE,OAAO,CNqH1B,GAAO,CMpHvB,qBAAqC,CAAE,OAAO,CN9N1B,GAAO,CM+N3B,4BAA4C,CAAE,OAAO,CN1F1B,GAAO,CM2FlC,iBAAiC,CAAE,OAAO,CN2F1B,GAAO,CM1FvB,iBAAiC,CAAE,OAAO,CNc1B,GAAO,CMbvB,8BAA8C,CAAE,OAAO,CNtM1B,GAAO,CMuMpC,+BAA+C,CAAE,OAAO,CNtM1B,GAAO,CMuMrC,4BAA4C,CAAE,OAAO,CNtM1B,GAAO,CMuMlC,8BAA8C,CAAE,OAAO,CN1M1B,GAAO,CM2MpC,gBAAgC,CAAE,OAAO,CN7C1B,GAAO,CM8CtB,eAA+B,CAAE,OAAO,CNtK1B,GAAO,CMuKrB,iBAAiC,CAAE,OAAO,CN9S1B,GAAO,CM+SvB,qBAAqC,CAAE,OAAO,CN+M1B,GAAO,CM9M3B,mBAAmC,CAAE,OAAO,CN/O1B,GAAO,CMgPzB,qBAAqC,CAAE,OAAO,CNtJ1B,GAAO,CMuJ3B,qBAAqC,CAAE,OAAO,CNtJ1B,GAAO,CMuJ3B,qBAAqC,CAAE,OAAO,CNmF1B,GAAO,CMlF3B,sBAAsC,CAAE,OAAO,CN6C1B,GAAO,CM5C5B,iBAAiC,CAAE,OAAO,CN0K1B,GAAO,CMzKvB,uBAAuC,CAAE,OAAO,CNO1B,GAAO,CMN7B,wIAAyC,CAAE,OAAO,CNO1B,GAAO,CMN/B,mBAAmC,CAAE,OAAO,CN/B1B,GAAO,CMgCzB,qBAAqC,CAAE,OAAO,CNjC1B,GAAO,CMkC3B,uBAAuC,CAAE,OAAO,CN3N1B,GAAO,CM4N7B,wBAAwC,CAAE,OAAO,CNyB1B,GAAO,CMxB9B,+BAA+C,CAAE,OAAO,CNlJ1B,GAAO,CMmJrC,uBAAuC,CAAE,OAAO,CNuF1B,GAAO,CMtF7B,kBAAkC,CAAE,OAAO,CN9L1B,GAAO,CM+LxB,qDAC8C,CAAE,OAAO,CNnP1B,GAAO,CMoPpC,iDAC4C,CAAE,OAAO,CNlP1B,GAAO,CMmPlC,uDAC+C,CAAE,OAAO,CNrP1B,GAAO,CMsPrC,8BAC8B,CAAE,OAAO,CNpK1B,GAAO,CMqKpB,cAA8B,CAAE,OAAO,CNzG1B,GAAO,CM0GpB,gCAC8B,CAAE,OAAO,CNwL1B,GAAO,CMvLpB,+BAC8B,CAAE,OAAO,CNrE1B,GAAO,CMsEpB,2DAG8B,CAAE,OAAO,CNnE1B,GAAO,CMoEpB,iDAE8B,CAAE,OAAO,CNqD1B,GAAO,CMpDpB,6BAC8B,CAAE,OAAO,CNpE1B,GAAO,CMqEpB,iCAC8B,CAAE,OAAO,CN1R1B,GAAO,CM2RpB,eAA+B,CAAE,OAAO,CNlK1B,GAAO,CMmKrB,oBAAoC,CAAE,OAAO,CNtJ1B,GAAO,CMuJ1B,yBAAyC,CAAE,OAAO,CN4E1B,GAAO,CM3E/B,0BAA0C,CAAE,OAAO,CN4E1B,GAAO,CM3EhC,0BAA0C,CAAE,OAAO,CN4E1B,GAAO,CM3EhC,2BAA2C,CAAE,OAAO,CN4E1B,GAAO,CM3EjC,2BAA2C,CAAE,OAAO,CN+E1B,GAAO,CM9EjC,4BAA4C,CAAE,OAAO,CN+E1B,GAAO,CM9ElC,oBAAoC,CAAE,OAAO,CN+H1B,GAAO,CM9H1B,sBAAsC,CAAE,OAAO,CN2H1B,GAAO,CM1H5B,yBAAyC,CAAE,OAAO,CN4L1B,GAAO,CM3L/B,kBAAkC,CAAE,OAAO,CNyL1B,GAAO,CMxLxB,eAA+B,CAAE,OAAO,CNmL1B,GAAO,CMlLrB,sBAAsC,CAAE,OAAO,CNmL1B,GAAO,CMlL5B,uBAAuC,CAAE,OAAO,CNuL1B,GAAO,CMtL7B,kBAAkC,CAAE,OAAO,CN/M1B,GAAO,CMgNxB,yBAAyC,CAAE,OAAO,CNgF1B,GAAO,CM/E/B,oBAAoC,CAAE,OAAO,CNjG1B,GAAO,CMkG1B,iBAAiC,CAAE,OAAO,CNxJ1B,GAAO,CMyJvB,cAA8B,CAAE,OAAO,CNhX1B,GAAO,CMiXpB,2CAAoC,CAAE,OAAO,CNzT1B,GAAO,CM0T1B,2BAA2C,CAAE,OAAO,CNzT1B,GAAO,CM0TjC,iBAAiC,CAAE,OAAO,CNqI1B,GAAO,CMpIvB,wBAAwC,CAAE,OAAO,CNqI1B,GAAO,CMpI9B,0BAA0C,CAAE,OAAO,CNrE1B,GAAO,CMsEhC,wBAAwC,CAAE,OAAO,CNnE1B,GAAO,CMoE9B,0BAA0C,CAAE,OAAO,CNtE1B,GAAO,CMuEhC,2BAA2C,CAAE,OAAO,CNtE1B,GAAO,CMuEjC,gBAAgC,CAAE,OAAO,CNxW1B,GAAO,CMyWtB,kBAAkC,CAAE,OAAO,CN8J1B,GAAO,CM7JxB,kBAAkC,CAAE,OAAO,CNpX1B,GAAO,CMqXxB,gBAAgC,CAAE,OAAO,CNnF1B,GAAO,CMoFtB,mBAAmC,CAAE,OAAO,CNjO1B,GAAO,CMkOzB,gBAAgC,CAAE,OAAO,CNsC1B,GAAO,CMrCtB,qBAAqC,CAAE,OAAO,CNhK1B,GAAO,CMiK3B,iBAAiC,CAAE,OAAO,CNmH1B,GAAO,CMlHvB,iBAAiC,CAAE,OAAO,CNxM1B,GAAO,CMyMvB,eAA+B,CAAE,OAAO,CNzE1B,GAAO,CM0ErB,iBAAiC,CAAE,OAAO,CNrJ1B,GAAO,CMsJvB,gBAAgC,CAAE,OAAO,CN2E1B,GAAO,CM1EtB,iBAAiC,CAAE,OAAO,CN7D1B,GAAO,CM8DvB,kBAAkC,CAAE,OAAO,CNpX1B,GAAO,CMqXxB,cAA8B,CAAE,OAAO,CNpU1B,GAAO,CMqUpB,aAA6B,CAAE,OAAO,CNsI1B,GAAO,CMrInB,gBAAgC,CAAE,OAAO,CN2I1B,GAAO,CM1ItB,iBAAiC,CAAE,OAAO,CNX1B,GAAO,CMYvB,oBAAoC,CAAE,OAAO,CN5D1B,GAAO,CM6D1B,yBAAyC,CAAE,OAAO,CNgD1B,GAAO,CM/C/B,+BAA+C,CAAE,OAAO,CNrX1B,GAAO,CMsXrC,8BAA8C,CAAE,OAAO,CNvX1B,GAAO,CMwXpC,qDAC8C,CAAE,OAAO,CN5T1B,GAAO,CM6TpC,uBAAuC,CAAE,OAAO,CNvP1B,GAAO,CMwP7B,qBAAqC,CAAE,OAAO,CNoI1B,GAAO,CMnI3B,uBAAuC,CAAE,OAAO,CNyH1B,GAAO,CMxH7B,sCAC8B,CAAE,OAAO,CNiG1B,GAAO,CMhGpB,wEAAwC,CAAE,OAAO,CNzC1B,GAAO,CM0C9B,wBAAwC,CAAE,OAAO,CN+B1B,GAAO,CM9B9B,gBAAgC,CAAE,OAAO,CNa1B,GAAO,CMZtB,0BAA0C,CAAE,OAAO,CNnP1B,GAAO,CMoPhC,oBAAoC,CAAE,OAAO,CNgI1B,GAAO,CM/H1B,iBAAiC,CAAE,OAAO,CN9E1B,GAAO,CM+EvB,4DAEqC,CAAE,OAAO,CNmG1B,GAAO,CMlG3B,iDACyC,CAAE,OAAO,CN3K1B,GAAO,CM4K/B,gBAAgC,CAAE,OAAO,CN6H1B,GAAO,CM5HtB,iBAAiC,CAAE,OAAO,CNjL1B,GAAO,CMkLvB,iBAAiC,CAAE,OAAO,CNxC1B,GAAO,CMyCvB,wBAAwC,CAAE,OAAO,CNxC1B,GAAO,CMyC9B,6BAA6C,CAAE,OAAO,CNuC1B,GAAO,CMtCnC,sBAAsC,CAAE,OAAO,CNqC1B,GAAO,CMpC5B,oBAAoC,CAAE,OAAO,CNlR1B,GAAO,CMmR1B,eAA+B,CAAE,OAAO,CNhR1B,GAAO,CMiRrB,qBAAqC,CAAE,OAAO,CNxE1B,GAAO,CMyE3B,yBAAyC,CAAE,OAAO,CNxE1B,GAAO,CMyE/B,iBAAiC,CAAE,OAAO,CN7Q1B,GAAO,CM8QvB,iBAAiC,CAAE,OAAO,CN3J1B,GAAO,CM4JvB,mBAAmC,CAAE,OAAO,CNtJ1B,GAAO,CMuJzB,cAA8B,CAAE,OAAO,CNtP1B,GAAO,CMuPpB,mBAAmC,CAAE,OAAO,CN3W1B,GAAO,CM4WzB,gBAAgC,CAAE,OAAO,CNjU1B,GAAO,CMkUtB,cAA8B,CAAE,OAAO,CN1F1B,GAAO,CM2FpB,gBAAgC,CAAE,OAAO,CNM1B,GAAO,CMLtB,eAA+B,CAAE,OAAO,CNrS1B,GAAO,CMsSrB,gBAAgC,CAAE,OAAO,CNrS1B,GAAO,CMsStB,kBAAkC,CAAE,OAAO,CNtY1B,GAAO,CMuYxB,yBAAyC,CAAE,OAAO,CNtY1B,GAAO,CMuY/B,gBAAgC,CAAE,OAAO,CNa1B,GAAO,CMZtB,uBAAuC,CAAE,OAAO,CNa1B,GAAO,CMZ7B,kBAAkC,CAAE,OAAO,CN/D1B,GAAO,CMgExB,oCAC8B,CAAE,OAAO,CN5W1B,GAAO,CM6WpB,8BAC+B,CAAE,OAAO,CN2B1B,GAAO,CM1BrB,eAA+B,CAAE,OAAO,CNoD1B,GAAO,CMnDrB,kBAAkC,CAAE,OAAO,CNN1B,GAAO,CMOxB,qBAAqC,CAAE,OAAO,CNzS1B,GAAO,CM0S3B,qBAAqC,CAAE,OAAO,CNZ1B,GAAO,CMa3B,mBAAmC,CAAE,OAAO,CN/S1B,GAAO,CMgTzB,qBAAqC,CAAE,OAAO,CNhQ1B,GAAO,CMiQ3B,sBAAsC,CAAE,OAAO,CNzP1B,GAAO,CM0P5B,uBAAuC,CAAE,OAAO,CNtQ1B,GAAO,CMuQ7B,4BAA4C,CAAE,OAAO,CNhQ1B,GAAO,CMiQlC,yEAEuC,CAAE,OAAO,CNzQ1B,GAAO,CM0Q7B,+CACyC,CAAE,OAAO,CN/Q1B,GAAO,CMgR/B,+CACuC,CAAE,OAAO,CNhR1B,GAAO,CMiR7B,+CACuC,CAAE,OAAO,CNrQ1B,GAAO,CMsQ7B,sBAAsC,CAAE,OAAO,CNlR1B,GAAO,CMmR5B,eAA+B,CAAE,OAAO,CN4D1B,GAAO,CM3DrB,kBAAkC,CAAE,OAAO,CNrV1B,GAAO,CMsVxB,mBAAmC,CAAE,OAAO,CNhM1B,GAAO,CMiMzB,uGAIoC,CAAE,OAAO,CNtL1B,GAAO,CMuL1B,yBAAyC,CAAE,OAAO,CNvW1B,GAAO,CMwW/B,8BACgC,CAAE,OAAO,CNlG1B,GAAO,CMmGtB,+BACiC,CAAE,OAAO,CN1T1B,GAAO,CM2TvB,qBAAqC,CAAE,OAAO,CNpP1B,GAAO,CMqP3B,cAA8B,CAAE,OAAO,CNtP1B,GAAO,CMuPpB,sBAAsC,CAAE,OAAO,CNxO1B,GAAO,CMyO5B,wBAAwC,CAAE,OAAO,CNR1B,GAAO,CMS9B,aAA6B,CAAE,OAAO,CNjH1B,GAAO,CMkHnB,mCACiC,CAAE,OAAO,CNiD1B,GAAO,CMhDvB,sCACsC,CAAE,OAAO,CNrJ1B,GAAO,CMsJ5B,0CACwC,CAAE,OAAO,CNtJ1B,GAAO,CMuJ9B,kBAAkC,CAAE,OAAO,CNvO1B,GAAO,CMwOxB,sBAAsC,CAAE,OAAO,CNvX1B,GAAO,CMwX5B,iBAAiC,CAAE,OAAO,CN7O1B,GAAO,CM8OvB,oBAAoC,CAAE,OAAO,CNxJ1B,GAAO,CMyJ1B,kBAAkC,CAAE,OAAO,CNvE1B,GAAO,CMwExB,oBAAoC,CAAE,OAAO,CNtF1B,GAAO,CMuF1B,2BAA2C,CAAE,OAAO,CNtF1B,GAAO,CMuFjC,eAA+B,CAAE,OAAO,CNnb1B,GAAO,CMobrB,4CACmC,CAAE,OAAO,CNjR1B,GAAO,CMkRzB,cAA8B,CAAE,OAAO,CNI1B,GAAO,CMHpB,qBAAqC,CAAE,OAAO,CN9b1B,GAAO,CM+b3B,eAA+B,CAAE,OAAO,CN5I1B,GAAO,CM6IrB,qBAAqC,CAAE,OAAO,CN/E1B,GAAO,CMgF3B,iBAAiC,CAAE,OAAO,CNI1B,GAAO,CMHvB,eAA+B,CAAE,OAAO,CNuC1B,GAAO,CMtCrB,sBAAsC,CAAE,OAAO,CN7K1B,GAAO,CM8K5B,eAA+B,CAAE,OAAO,CN6B1B,GAAO,CM5BrB,qBAAqC,CAAE,OAAO,CNjb1B,GAAO,CMkb3B,iBAAiC,CAAE,OAAO,CNpK1B,GAAO,CMqKvB,wBAAwC,CAAE,OAAO,CNzQ1B,GAAO,CM0Q9B,kBAAkC,CAAE,OAAO,CNha1B,GAAO,CMiaxB,wBAAwC,CAAE,OAAO,CNpa1B,GAAO,CMqa9B,sBAAsC,CAAE,OAAO,CNta1B,GAAO,CMua5B,kBAAkC,CAAE,OAAO,CNxa1B,GAAO,CMyaxB,oBAAoC,CAAE,OAAO,CNta1B,GAAO,CMua1B,oBAAoC,CAAE,OAAO,CNta1B,GAAO,CMua1B,qBAAqC,CAAE,OAAO,CNjd1B,GAAO,CMkd3B,uBAAuC,CAAE,OAAO,CNjd1B,GAAO,CMkd7B,gBAAgC,CAAE,OAAO,CNtB1B,GAAO,CMuBtB,oBAAoC,CAAE,OAAO,CN9X1B,GAAO,CM+X1B,aAA6B,CAAE,OAAO,CNne1B,GAAO,CMoenB,qBAAqC,CAAE,OAAO,CNtV1B,GAAO,CMuV3B,sBAAsC,CAAE,OAAO,CN1L1B,GAAO,CM2L5B,wBAAwC,CAAE,OAAO,CNpd1B,GAAO,CMqd9B,qBAAqC,CAAE,OAAO,CNzf1B,GAAO,CM0f3B,oBAAoC,CAAE,OAAO,CN7K1B,GAAO,CM8K1B,qBAAqC,CAAE,OAAO,CNzO1B,GAAO,CM0O3B,iBAAiC,CAAE,OAAO,CNtP1B,GAAO,CMuPvB,wBAAwC,CAAE,OAAO,CNtP1B,GAAO,CMuP9B,qBAAqC,CAAE,OAAO,CNrC1B,GAAO,CMsC3B,oBAAoC,CAAE,OAAO,CNrC1B,GAAO,CMsC1B,kBAAkC,CAAE,OAAO,CN9d1B,GAAO,CM+dxB,cAA8B,CAAE,OAAO,CN5c1B,GAAO,CM6cpB,kBAAkC,CAAE,OAAO,CNtQ1B,GAAO,CMuQxB,oBAAoC,CAAE,OAAO,CN9gB1B,GAAO,CM+gB1B,aAA6B,CAAE,OAAO,CN/b1B,GAAO,CMgcnB,kDAE8B,CAAE,OAAO,CNpR1B,GAAO,CMqRpB,mBAAmC,CAAE,OAAO,CN/N1B,GAAO,COtUzB,swBAAK,CACH,WAAW,CAAE,OAAO,CACpB,y5BAAQ,CACN,WAAW,CC+BuB,aAAa,CD9B/C,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,MAAM,CAClB,WAAW,CAAE,MAAM,CACnB,WAAW,CAAE,CAAC,CACd,eAAe,CAAE,OAAO,CAM5B,86BAAkB,CAChB,OAAO,CAAE,YAAY,CACrB,eAAe,CAAE,OAAO,CAGxB,muEAAgB,CACd,OAAO,CAAE,MAAM,CACf,2wEAAuB,CACrB,WAAW,CAAE,KAAI,CACnB,utEAAsB,CACpB,OAAO,CAAE,YAAY,CAE3B,2iBAA2B,CACzB,OAAO,CAAE,GAAE,CfpBL,kBAAoB,CAAE,qBAAM,CAK5B,eAAiB,CAAE,qBAAM,CAezB,UAAY,CAAE,qBAAM,CeE5B,+nBAAiC,CAC/B,OAAO,CAAE,CAAC,CAGV,mtCAAuB,CACrB,SAAS,CAAE,IAAI,CACf,cAAc,CAAE,IAAI,CEpBxB,0PAAS,CACP,OAAO,CAAE,IAAqB,CAC9B,WAAW,CDayB,IAAI,CCZxC,aAAa,CDYuB,IAAI,CCXxC,UAAU,CAAE,OAAmB,CAEjC,8CAAe,CACb,KAAK,CDkC+B,IAAM,CCjC1C,WAAW,CAAE,IAAI,CACjB,OAAO,CAAE,KAAK,CACd,KAAK,CD+B+B,IAAM,CC9B1C,UAAU,CAAE,OAAkB,CAC9B,MAAM,CAAE,KAAsB,CAC9B,OAAO,CAAE,QAA2C,CACpD,aAAa,CAAE,IAAqB,CAEtC,0ZAAyB,CACvB,UAAU,CAAE,OAAkB,CAC9B,mxCAAe,CACb,UAAU,CAAE,OAAiB,CACjC,kYAA0B,CACxB,UAAU,CAAE,OAAmB,CAC/B,ouCAAe,CACb,UAAU,CAAE,OAAoB,CAEpC,sYAAuB,CACrB,UAAU,CAAE,OAAmB,CAC/B,yuCAAe,CACb,UAAU,CAAE,OAAkB,CAElC,mZAA0B,CACxB,UAAU,CAAE,OAAuB,CACnC,swCAAe,CACb,UAAU,CAAE,OAAqB,CAErC,scAA0B,CACxB,UAAU,CDmB0B,OAAmB,CClBvD,42CAAe,CACb,KAAK,CCjD6B,OAAW,CDkD7C,UAAU,CDJwB,OAAmB,CCKvD,8dAAC,CACC,KAAK,CDsB6B,OAAW,CCpBjD,sZAAsB,CACpB,aAAa,CAAE,CAAC,CAsBlB,kBAAkB,CAChB,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,GAAG,CACX,IAAI,CAAE,CAAC,CACP,OAAO,CDG6B,GAAG,CCFvC,qBAAE,CACA,OAAO,CAAE,KAAK,CACd,KAAK,CDT6B,KAAK,CCUvC,UAAU,CAAE,WAAW,CACvB,KAAK,CDlC6B,IAAM,CCmCxC,UAAU,CAAE,MAAM,CAClB,UAAU,CAAE,2BAA0B,CACtC,OAAO,CAAE,MAAmB,CAC5B,SAAS,CAAE,GAAG,CACd,OAAO,CAAE,CAAC,CACV,MAAM,CAAE,CAAC,CACT,WAAW,CAAE,IAAI,CACjB,QAAQ,CAAE,MAAM,CjB3FZ,kBAAoB,CAAE,gBAAM,CAK5B,eAAiB,CAAE,gBAAM,CAezB,UAAY,CAAE,gBAAM,CiByExB,0CAAsB,CACpB,UAAU,CDhCsB,OAAM,CCiCxC,uCAAmB,CACjB,UAAU,CDzBsB,OAAW,CC0B7C,0CAAsB,CACpB,UAAU,CDnFsB,OAAO,CCoFzC,yCAAqB,CACnB,UAAU,CDtEsB,OAAI,CCuEtC,wBAAI,CACF,OAAO,CAAE,CAAC,CACV,MAAM,CAAE,IAAI,CEhFd,oCAAsB,CFmFxB,kBAAkB,CAChB,MAAM,CAAE,IAAI,CACZ,GAAG,CAAE,CAAC,CACN,KAAK,CAAE,IAAI,CACX,qBAAE,CACA,KAAK,CAAE,IAAI,EG3FjB,MAAM,CACJ,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,CAAC,CACT,cAAc,CAAE,QAAQ,CACxB,eAAe,CAAE,MAAM,CACvB,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,MAAM,CACnB,kBAAkB,CAAE,MAAM,CAC1B,SAAS,CAAE,OAAO,CACpB,gDAAiD,CAC/C,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACZ,gBAAgB,CACd,MAAM,CAAE,OAAO,CAEjB,IAAI,CAEF,OAAO,CAAE,YAAY,CACrB,aAAa,CAAE,GAAG,CAClB,WAAW,CAAE,MAAM,CACnB,WAAW,CAAE,MAAM,CACnB,UAAU,CAAE,MAAM,CAClB,MAAM,CAAE,OAAO,CACf,SAAS,CAAE,IAAI,CACf,OAAO,CAAE,iBAA6F,CACtG,KAAK,CJI+B,IAAM,CIH1C,MAAM,CAAE,yBAAyB,CACjC,gBAAgB,CJeoB,OAAM,CId1C,eAAe,CAAE,IAAI,CACrB,WAAW,CAAE,MAAM,CACnB,WAAW,CFnDyB,uDAAM,CEoD1C,UAAU,CAAE,mFAA8C,CAC1D,YAAY,CAAE,KAAK,CACnB,cAAc,CAAE,MAAM,CACtB,QAAQ,CAAE,MAAM,CAChB,IAAI,CAAE,CAAC,CACP,iBAAiB,CAAE,IAAI,CpBxDjB,mBAAoB,CoByDb,IAAI,CpBpDX,gBAAiB,CoBoDV,IAAI,CpB/CX,eAAgB,CoB+CT,IAAI,CpBrCX,WAAY,CoBqCL,IAAI,CpBzDX,kBAAoB,CAAE,eAAM,CAK5B,eAAiB,CAAE,eAAM,CAezB,UAAY,CAAE,eAAM,CoByC5B,UAAU,CACR,UAAU,CAAE,OAAwB,CACpC,KAAK,CJd+B,IAAM,CIiB1C,UAAO,CACL,UAAU,CAAE,OAAqC,CACjD,KAAK,CJnB6B,IAAM,CIoB1C,UAAO,CACL,UAAU,CAAE,OAAqC,CACjD,OAAO,CAAE,CAAC,CACZ,WAAQ,CACN,UAAU,CAAE,6EAAyC,CACrD,OAAO,CAAE,iBAA6F,CACxG,YAAS,CACP,KAAK,CJ3B6B,IAAM,CI4B1C,aAAU,CACR,gBAAgB,CAAE,IAAI,CACtB,MAAM,CAAE,2DAA2D,CACnE,MAAM,CAAE,iBAAmB,CAC3B,OAAO,CAAE,GAAG,CACZ,MAAM,CAAE,WAAW,CACnB,UAAU,CAAE,IAAI,CAEpB,aAAa,CACX,gBAAgB,CAAE,IAAI,CACtB,MAAM,CAAE,2DAA2D,CACnE,MAAM,CAAE,iBAAmB,CAC3B,OAAO,CAAE,GAAG,CACZ,MAAM,CAAE,WAAW,CACnB,UAAU,CAAE,IAAI,CAChB,4DAA0B,CACxB,gBAAgB,CAAE,IAAI,CACtB,MAAM,CAAE,2DAA2D,CACnE,MAAM,CAAE,iBAAmB,CAC3B,OAAO,CAAE,GAAI,CACb,MAAM,CAAE,WAAW,CACnB,UAAU,CAAE,IAAI,CAGpB,sBAAsB,CACpB,OAAO,CAAE,CAAC,CACV,MAAM,CAAE,CAAC,CAEX,UAAU,CACR,SAAS,CAAE,GAAG,CAEhB,SAAS,CACP,gBAAgB,CAAE,kBAAgB,CAClC,eAAO,CACL,gBAAgB,CAAE,kBAA6B,CAEnD,YAAY,CACV,gBAAgB,CAAE,kBAA2C,CAC7D,KAAK,CAAE,kBAAsB,CAC7B,kBAAO,CACL,gBAAgB,CAAE,kBAAuD,CACzE,KAAK,CFzH6B,OAAW,CE0H/C,oBAAS,CACP,KAAK,CAAE,kBAAsB,CAEjC,YAAY,CACV,gBAAgB,CAAE,kBAAiB,CACnC,kBAAO,CACL,gBAAgB,CAAE,eAA6B,CAEnD,WAAW,CACT,gBAAgB,CAAE,kBAAe,CACjC,iBAAO,CACL,gBAAgB,CAAE,kBAA4B,CAElD,YAAY,CACV,gBAAgB,CAAE,kBAAkB,CACpC,kBAAO,CACL,gBAAgB,CAAE,kBAA+B,CACrD,WAAW,CACT,gBAAgB,CJvIoB,IAAI,CIwIxC,iBAAO,CACL,gBAAgB,CAAE,kBAAoC,CAE1D,SAAS,CACP,gBAAgB,CAAE,sBAAsB,CACxC,KAAK,CJxE+B,OAAW,CIyE/C,UAAU,CAAE,IAAI,CAChB,YAAY,CAAE,sBAAsB,CACpC,eAAO,CACL,gBAAgB,CAAE,sBAAsB,CACxC,KAAK,CAAE,kBAAoC,CAC3C,UAAU,CAAE,IAAI,CAClB,gBAAQ,CACN,gBAAgB,CAAE,sBAAsB,CACxC,KAAK,CAAE,kBAAoC,CAC3C,UAAU,CAAE,IAAI,CAClB,iBAAS,CACP,KAAK,CJnG6B,OAAO,CIqG7C,mCAAoC,CAClC,cAAc,CAAE,MAAM,CAExB,aAAa,CACX,aAAa,CJ1IuB,IAAI,CduExC,KAAK,CAAE,CAAC,CACR,wCAAS,CAEP,OAAO,CAAE,KAAK,CACd,OAAO,CAAE,EAAE,CACb,mBAAO,CACL,KAAK,CAAE,IAAI,CmB3Ff,YAAY,CACV,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,YAAY,CAIvB,qCAAqC,CACnC,OAAO,CAAE,KAAK,CAChB,iBAAiB,CACf,QAAQ,CAAE,QAAQ,CAClB,IAAI,CAAE,CAAC,CACP,OAAO,CAAE,IAAI,CACb,KAAK,CAAE,IAAI,CACX,GAAG,CAAE,IAAI,CACT,SAAS,CAAE,IAAI,CACf,UAAU,CL1B0B,OAAyB,CK2B7D,OAAO,CLmD6B,GAAG,CKlDvC,MAAM,CAAE,iBAAgC,CACxC,UAAU,CAAE,2BAA0B,CACtC,OAAO,CAAE,IAAqB,CAC9B,sBAAQ,CACN,OAAO,CAAE,KAAK,CACd,KAAK,CAAE,IAAI,CACX,KAAK,CHnC6B,OAAW,CGoC7C,WAAW,CAAE,MAAM,CACnB,SAAS,CAAE,GAAG,CACd,OAAO,CAAE,MAAuB,CAChC,MAAM,CAAE,OAAO,CACf,4BAAO,CACL,UAAU,CLiCsB,OAAW,CKhC3C,KAAK,CLU2B,IAAM,CKT1C,4BAAY,CACV,UAAU,CAAE,iBAAgC,CAC5C,MAAM,CAAE,KAAuB,CACjC,2BAAW,CACT,cAAc,CAAE,IAAqB,CACrC,gDAAoB,CAClB,KAAK,CAAE,IAAI,CACf,mCAAmB,CACjB,UAAU,CAAE,OAA4B,CACxC,cAAc,CAAE,SAAS,CACzB,WAAW,CAAE,GAAG,CAChB,SAAS,CAAE,GAAG,CACd,yCAAO,CACL,UAAU,CAAE,OAA4B,CAC1C,wCAAI,CACF,KAAK,CLN2B,IAAM,CKQ5C,6CAA6C,CAC3C,MAAM,CAAE,IAAI,CACZ,GAAG,CAAE,IAAI,CACT,IAAI,CAAE,IAAI,CACV,KAAK,CAAE,CAAC,CAGR,iDAAiB,CACf,UAAU,CLnEwB,OAAyB,CKoE3D,UAAU,CAAE,GAAG,CACjB,mDAAmB,CACjB,OAAO,CAAE,QAA2C,CACpD,yDAAO,CACL,UAAU,CLCsB,OAAW,CKA3C,KAAK,CLtB2B,IAAM,CKwB5C,+CAA+C,CAC7C,KAAK,CAAE,CAAC,CACR,IAAI,CAAE,IAAI,CACV,UAAU,CAAE,KAAK,CAGjB,yBAAQ,CACN,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,iBAA0B,CACzC,WAAW,CAAE,qBAAqB,CAClC,YAAY,CAAE,qBAAqB,CACnC,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,KAAK,CACd,GAAG,CAAE,IAAI,CACT,IAAI,CAAE,GAAG,CACT,WAAW,CAAE,IAAI,CACnB,gDAA+B,CAC7B,IAAI,CAAE,IAAI,CCtEZ,uBAAM,CACJ,OAAO,CAAE,KAAK,CAEhB,gIAA+C,CAC7C,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAChB,KAAK,CAAE,CAAC,CACR,cAAc,CAAE,MAAM,CAItB,wCAAO,CACL,OAAO,CAAE,YAAY,CACrB,cAAc,CAAE,MAAM,CACtB,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,YAA+C,CACvD,KAAK,CAAE,IAAI,CACf,4BAAW,CACT,KAAK,CAAE,IAAI,CACX,kCAAK,CACH,OAAO,CAAE,KAAK,CAChB,mCAAM,CACJ,UAAU,CAAE,GAAqB,CAEvC,QAAQ,CACN,MAAM,CAAE,CAAC,CACT,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACZ,MAAM,CACJ,OAAO,CAAE,KAAK,CACd,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACV,WAAW,CAAE,MAAM,CACnB,aAAa,CN/BuB,IAAI,CMgCxC,SAAS,CAAE,IAAI,CACf,YAAY,CAAE,IAAI,CACpB,KAAK,CACH,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,cAAa,CACrB,KAAK,CNR+B,IAAU,CMS9C,SAAS,CAAE,GAAG,CAEhB,qBAAuB,CACrB,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,CAAC,CACT,cAAc,CAAE,QAAQ,CACxB,eAAe,CAAE,MAAM,CAGzB,iBAAiB,CACf,aAAa,CNhDuB,IAAI,CduExC,KAAK,CAAE,CAAC,CqBrGR,SAAS,CCCC,IAAQ,CDChB,WAAI,CAAE,IAAI,CACV,YAAK,CAAE,IAAI,CrBkGb,KAAK,CAAE,CAAC,CACR,gDAAS,CAEP,OAAO,CAAE,KAAK,CACd,OAAO,CAAE,EAAE,CACb,uBAAO,CACL,KAAK,CAAE,IAAI,CALb,gDAAS,CAEP,OAAO,CAAE,KAAK,CACd,OAAO,CAAE,EAAE,CACb,uBAAO,CACL,KAAK,CAAE,IAAI,CoBzBf,uDAAyD,CACvD,OAAO,CAAE,IAAI,CACb,KAAK,CN/C+B,OAAI,CMoDxC,mGAA+C,CAC7C,cAAc,CAAE,IAAqB,CACrC,wHAAM,CACJ,KAAK,CAAE,IAAI,CAEX,0tEAAqP,CACnP,KAAK,CAAE,IAAI,CACnB,+BAA+B,CGlF3B,KAAK,CAAE,IAAsB,CAG3B,OAAO,CAAE,KAAK,CAed,YAAoB,CAAE,QAA+B,CACrD,KAAK,CAAE,IAAuC,CCnB5C,YAAoB,CAAE,CAAC,CDqBzB,0CAAa,CACX,YAAoB,CAAE,CAAC,CHgE/B,iCAAiC,CGtF7B,KAAK,CAAE,IAAsB,CAG3B,OAAO,CAAE,KAAK,CAed,YAAoB,CAAE,QAA+B,CACrD,KAAK,CAAE,SAAuC,CAE9C,4CAAa,CACX,YAAoB,CAAE,CAAC,CCA7B,iDAAwB,CACtB,YAAoB,CAAE,CAAC,CAEvB,mDAA0B,CACxB,KAAK,CALY,IAAkC,CJqEzD,iCAAiC,CG1F7B,KAAK,CAAE,IAAsB,CAG3B,OAAO,CAAE,KAAK,CAed,YAAoB,CAAE,QAA+B,CACrD,KAAK,CAAE,SAAuC,CAE9C,4CAAa,CACX,YAAoB,CAAE,CAAC,CCA7B,iDAAwB,CACtB,YAAoB,CAAE,CAAC,CAEvB,mDAA0B,CACxB,KAAK,CALY,IAAkC,CJ0EzD,uDAAuD,CACrD,MAAM,CAAE,SAA2B,CACnC,SAAS,CAAE,GAAG,CAEhB,oBAAoB,CAClB,OAAO,CAAE,YAAY,CACrB,MAAM,CAAE,SAA2B,CACnC,SAAS,CAAE,GAAG,CAOZ,osBAAqP,CACnP,KAAK,CAAE,IAAI,CAIjB,uBAAuB,CACrB,OAAO,CAAE,YAAY,CACrB,YAAY,CAAE,KAAK,CACnB,KAAK,CAAE,IAAI,CACX,cAAc,CAAE,MAAM,CACtB,SAAS,CAAE,GAAG,CAEhB,gBAAgB,CACd,OAAO,CAAE,KAAK,CACd,KAAK,CN7H+B,IAAI,CM8HxC,SAAS,CAAE,GAAG,CACd,UAAU,CAAE,QAAO,CACnB,UAAU,CAAE,MAAM,CAClB,kBAAC,CACC,SAAS,CAAE,OAAO,CAClB,UAAU,CAAE,MAAM,CAClB,aAAa,CAAE,GAAqB,CACtC,6BAAY,CACV,aAAa,CAAE,CAAC,CA4DpB,KAAK,CACH,WAAW,CAAE,MAAM,CAGnB,6DAAmD,CACjD,kBAAkB,CAAE,MAAM,CAC1B,MAAM,CAAE,OAAO,CACf,WAAW,CJ/MuB,uDAAM,CIgNxC,SAAS,CAAE,OAAO,CACpB,gSAAqP,CACnP,kBAAkB,CAAE,IAAI,CACxB,OAAO,CAAE,GAAqB,CAC9B,OAAO,CAAE,YAAY,CACrB,MAAM,CAAE,cAA6B,CACrC,SAAS,CAAE,GAAG,CACd,WAAW,CJvNuB,uDAAM,CIwNxC,UAAU,CAAE,oBAAmC,CAC/C,aAAa,CAAE,CAAC,CtBxNZ,kBAAoB,CAAE,kBAAM,CAK5B,eAAiB,CAAE,kBAAM,CAezB,UAAY,CAAE,kBAAM,CsBuM1B,4BAAwB,CACtB,OAAO,CAAE,iBAAkB,CAC7B,eAAW,CACT,MAAM,CAAE,OAAO,CACjB,0CAAmC,CtB/N7B,kBAAoB,CsBgOZ,UAAU,CtB3NlB,eAAiB,CsB2NT,UAAU,CtB5MlB,UAAY,CsB4MJ,UAAU,CACtB,OAAO,CAAE,CAAC,CACV,YAAY,CAAE,QAAO,CACrB,OAAO,CAAE,IAAI,CACb,MAAM,CAAE,IAAI,CACd,oBAAgB,CtBrOV,kBAAoB,CsBsOZ,UAAU,CtBjOlB,eAAiB,CsBiOT,UAAU,CtBlNlB,UAAY,CsBkNJ,UAAU,CACtB,kGAA6D,CAC3D,kBAAkB,CAAE,IAAI,CAC5B,oXAAyU,CACvU,OAAO,CAAE,CAAC,CACV,OAAO,CAAE,cAAc,CACvB,YAAY,CNxLsB,IAAU,CMyL9C,oBAAgB,CACd,YAAY,CAAE,eAA8B,CAC9C,+EAAqE,CACnE,OAAO,CAAE,gBAAsB,CAC/B,OAAO,CAAE,gBAAgB,CAC3B,4aAAiY,CAC/X,MAAM,CAAE,WAAW,CACnB,gBAAgB,CAAE,OAAmC,CAEzD,+DAAiE,CAC/D,KAAK,CNzN+B,OAAI,CM0NxC,MAAM,CAAE,iBAAc,CACxB,iFAAmF,CACjF,YAAY,CN5NwB,OAAI,CM8NxC,yHAA+G,CAC7G,aAAa,CN/NqB,OAAI,CMiO1C,oBAAoB,CAClB,OAAO,CAAE,IAAqB,CAC9B,SAAS,CAAE,IAAI,CAKjB,QAAQ,CACN,QAAQ,CAAE,IAAI,CACd,cAAc,CAAE,GAAG,CACnB,KAAK,CAAE,IAAI,CACX,WAAW,CJ3QyB,uDAAM,CI4Q5C,eAAgB,CACd,OAAO,CAAE,aAAgB,CACzB,OAAO,CAAE,YAAY,CACrB,MAAM,CAAE,cAA6B,CACrC,SAAS,CAAE,GAAG,CACd,UAAU,CAAE,oBAAmC,CtBhRzC,kBAAoB,CAAE,kBAAM,CAK5B,eAAiB,CAAE,kBAAM,CAezB,UAAY,CAAE,kBAAM,CsB+P5B,MAAM,CACJ,MAAM,CAAE,cAA6B,CACrC,gBAAgB,CNpOoB,IAAM,CMqO1C,gBAAW,CACT,MAAM,CAAE,IAAI,CAChB,2BAA4B,CAC1B,OAAO,CAAE,CAAC,CACZ,uFAA2F,CACzF,MAAM,CAAE,WAAW,CACnB,gBAAgB,CAAE,OAAmC,CAKrD,8DAAuD,CACrD,MAAM,CAAE,WAAW,CACvB,sBAAuB,CACrB,MAAM,CAAE,KAAuB,CAE/B,KAAK,CJzS+B,OAAW,CI0S/C,OAAO,CAAE,KAAK,CACd,kCAAK,CACH,cAAc,CAAE,QAAQ,CAI5B,uBAAuB,CACrB,OAAO,CAAE,YAAY,CACrB,QAAQ,CAAE,MAAM,CAChB,KAAK,CAAE,CAAC,CACR,cAAc,CAAE,MAAM,CAuBxB,iCAAkC,CAChC,WAAW,CAAE,MAAM,CACnB,OAAO,CAAE,GAAqB,CAC9B,qEAAiB,CACf,WAAW,CAAE,IAAI,CACjB,OAAO,CAAE,KAAK,CACd,OAAO,CAAE,YAAY,CACrB,SAAS,CAAE,GAAG,CACd,gBAAgB,CNjRkB,OAAmB,CMkRrD,MAAM,CAAE,cAA6B,CACrC,KAAK,CN7U6B,IAAI,CM+U1C,kCAAkC,CAChC,WAAW,CAAE,CAAC,CAChB,kCAAkC,CAChC,YAAY,CAAE,CAAC,CAcjB,UAAU,CACR,KAAK,CAAE,IAAuB,CAC9B,MAAM,CAAE,IAAqB,CAC7B,MAAM,CAAE,MAAwB,CAChC,QAAQ,CAAE,QAAQ,CAClB,aAAa,CAAE,GAAG,CAClB,UAAU,CNrW0B,IAAI,CMsWxC,MAAM,CAAE,OAAO,CtB5WT,kBAAoB,CAAE,oBAAM,CAK5B,eAAiB,CAAE,oBAAM,CAezB,UAAY,CAAE,oBAAM,CsB0V1B,iBAAQ,CACN,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,EAAE,CACX,OAAO,CAAE,KAAK,CACd,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,aAAa,CAAE,GAAG,CAClB,UAAU,CNhXwB,IAAI,CMiXtC,IAAI,CAAE,IAAI,CACV,GAAG,CAAE,IAAI,CtBvXL,kBAAoB,CAAE,oBAAM,CAK5B,eAAiB,CAAE,oBAAM,CAezB,UAAY,CAAE,oBAAM,CsBqW1B,gBAAO,CACL,OAAO,CAAE,OAAO,CAChB,QAAQ,CAAE,QAAQ,CAClB,IAAI,CAAE,IAAqB,CAC3B,OAAO,CAAE,KAAK,CACd,SAAS,CAAE,IAAI,CACf,KAAK,CNzX6B,IAAI,CM0X1C,iBAAiB,CACf,UAAU,CAAE,OAAmB,CAC/B,wBAAQ,CACN,IAAI,CN5W8B,IAAI,CM6WtC,UAAU,CNtUwB,OAAM,CMuU1C,uBAAO,CACL,OAAO,CAAE,MAAM,CAEnB,8CAA+C,CAC7C,MAAM,CAAE,WAAW,CAiDnB,wGAAyB,CACvB,KAAK,CN7Z6B,OAAI,CM+ZtC,81BAAqP,CACnP,MAAM,CAAE,iBAAc,CAC1B,iDAAQ,CACN,MAAM,CAAE,iBAAc,CAE1B,mBAAmB,CACjB,WAAW,CAAE,MAAM,CACnB,qCAAiB,CACf,OAAO,CAAE,aAAgB,CACzB,OAAO,CAAE,YAAY,CACrB,SAAS,CAAE,GAAG,CAClB,gEAAgE,CAC9D,KAAK,CN3Y+B,OAAM,CM8Y5C,+DAA+D,CAC7D,KAAK,CN/a+B,OAAI,CMkb1C,gEAAgE,CAC9D,KAAK,CNlc+B,OAAO,CMqc7C,6DAA6D,CAC3D,KAAK,CN9Y+B,OAAW,CMoZjD,UAAU,CtB3dF,iBAAoB,CAAE,aAAM,CAK5B,cAAiB,CAAE,aAAM,CAKzB,aAAgB,CAAE,aAAM,CAKxB,YAAe,CAAE,aAAM,CAKvB,SAAY,CAAE,aAAM,CsByc5B,WAAW,CtB7dH,iBAAoB,CAAE,cAAM,CAK5B,cAAiB,CAAE,cAAM,CAKzB,aAAgB,CAAE,cAAM,CAKxB,YAAe,CAAE,cAAM,CAKvB,SAAY,CAAE,cAAM,CsB2c5B,WAAW,CtB/dH,iBAAoB,CAAE,cAAM,CAK5B,cAAiB,CAAE,cAAM,CAKzB,aAAgB,CAAE,cAAM,CAKxB,YAAe,CAAE,cAAM,CAKvB,SAAY,CAAE,cAAM,CsB6c5B,OAAO,CtBjeC,iBAAoB,CAAE,UAAM,CAK5B,cAAiB,CAAE,UAAM,CAKzB,aAAgB,CAAE,UAAM,CAKxB,YAAe,CAAE,UAAM,CAKvB,SAAY,CAAE,UAAM,CsB+c1B,iBAAW,CtBneL,iBAAoB,CsBoeL,wBAAwB,CtB/dvC,cAAiB,CsB+dF,wBAAwB,CtB1dvC,aAAgB,CsB0dD,wBAAwB,CtBrdvC,YAAe,CsBqdA,wBAAwB,CtBhdvC,SAAY,CsBgdG,wBAAwB,CAC7C,kBAAY,CtBreN,iBAAoB,CsBseL,yBAAyB,CtBjexC,cAAiB,CsBieF,yBAAyB,CtB5dxC,aAAgB,CsB4dD,yBAAyB,CtBvdxC,YAAe,CsBudA,yBAAyB,CtBldxC,SAAY,CsBkdG,yBAAyB,CAC9C,kBAAY,CtBveN,iBAAoB,CsBweL,yBAAyB,CtBnexC,cAAiB,CsBmeF,yBAAyB,CtB9dxC,aAAgB,CsB8dD,yBAAyB,CtBzdxC,YAAe,CsBydA,yBAAyB,CtBpdxC,SAAY,CsBodG,yBAAyB,CAEhD,yCAAyC,CAErC,8BAAqB,CACnB,MAAM,CAAE,SAAS,CAEjB,8ZAAqP,CACnP,aAAa,CAAE,KAAK,CACpB,OAAO,CAAE,KAAK,CAClB,cAAK,CACH,aAAa,CAAE,KAAK,CACpB,OAAO,CAAE,KAAK,CAEhB,kYAAqO,CACnO,aAAa,CAAE,CAAC,CAElB,wCAAuB,CACrB,aAAa,CAAE,KAAK,CACpB,UAAU,CAAE,IAAI,CAChB,OAAO,CAAE,KAAK,CACd,KAAK,CAAE,IAAI,CACb,4BAAW,CACT,MAAM,CAAE,WAAW,CACvB,iEAAmE,CACjE,OAAO,CAAE,KAAK,CACd,SAAS,CAAE,GAAG,CACd,OAAO,CAAE,KAAuB,EH5ehC,oCAAsB,CQhC1B,YAAY,CAER,OAAO,CAAE,IAAI,ER8Bb,oCAAsB,CQ5B1B,YAAY,CAER,OAAO,CAAE,IAAI,EAEjB,WAAW,CACT,KAAK,CAAE,IAAI,CAEb,YAAY,CACV,KAAK,CAAE,KAAK,CAEd,WAAW,CACT,KAAK,CAAE,IAAI,CC4Cb,mEAAS,CACP,eAAe,CAAE,QAAQ,CACzB,cAAc,CAAE,CAAC,CACjB,WAAW,CAAE,IAAI,CACjB,aAAa,CZ/BuB,IAAI,CYgCxC,2FAAO,CACL,KAAK,CAAE,IAAI,CACX,IAAI,CAAE,6BAAkB,CACxB,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,MAAM,CACpB,yJAAM,CACJ,SAAS,CZjByB,GAAG,CYkBrC,MAAM,CAAE,CAAC,CACT,QAAQ,CAAE,OAAO,CACjB,OAAO,CZnB2B,QAAmC,CYoBvE,iOAA8B,CAC5B,iBAAiB,CAAE,CAAC,CACtB,qFAAK,CACH,KAAK,CAAE,IAAI,CACX,UAAU,CAAE,IAAI,CAChB,cAAc,CAAE,MAAM,CACtB,WAAW,CAAE,MAAM,CACnB,8FAAE,CACA,WAAW,CZnDqB,IAAI,CYoDpC,aAAa,CAAE,iBAA6B,CAChD,4EAAE,CACA,gBAAgB,CAAE,WAAW,CAC7B,cAAc,CAAE,MAAM,CAE1B,kFAAc,CACZ,WAAW,CAAE,IAAuB,CACpC,mHAAY,CACV,aAAa,CAAE,CAAC,CACpB,4HAA4B,CAC1B,KAAK,CAAE,EAAE,CACT,aAAa,CAAE,CAAC,CAChB,uXAA0C,CACxC,MAAM,CAAE,CAAC,CAEb,mBAAmB,CACjB,KAAK,CZxD+B,IAAwB,CYyD5D,SAAS,CAAE,GAAG,CAChB,kBAAkB,CAChB,KAAK,CZ3D+B,IAAwB,CY4D5D,SAAS,CAAE,GAAG,CAIhB,2HAAyD,CACvD,gBAAgB,CZpCoB,OAAmB,CYsCzD,gBAAgB,CACd,gBAAgB,CZvCoB,OAAmB,CY4CzD,kDAAsB,CACpB,MAAM,CAAE,iBAA6B,CACrC,wDAAE,CACA,aAAa,CAAE,iBAA6B,CAC5C,WAAW,CAAE,iBAA6B,CAC5C,gGAAwB,CACtB,mBAAmB,CAAE,CAAC,CAE1B,kBAAkB,CAChB,MAAM,CAAE,iBAA6B,CAGrC,0BAAE,CACA,aAAa,CAAE,iBAA6B,CAC9C,8CAAwB,CACtB,mBAAmB,CAAE,CAAC,CAGxB,2CAAwB,CACtB,mBAAmB,CAAE,CAAC,CACxB,+CAAM,CACJ,YAAY,CAAE,SAAS,CACvB,aAAa,CAAE,iBAA6B,CAC9C,2CAAwB,CACtB,mBAAmB,CAAE,CAAC,CAG1B,oBAAoB,CAClB,aAAa,CZhHuB,IAAI,CYiHxC,SAAS,CAAE,IAAI,CACf,QAAQ,CAAE,IAAI,CACd,0BAAK,CACH,aAAa,CAAE,YAAY,CAC3B,2DAAM,CACJ,WAAW,CAAE,MAAM,CCzIzB,CAAC,CACC,KAAK,CbkE+B,OAAW,CajE/C,eAAe,CAAE,IAAI,CACrB,MAAM,CAAE,OAAO,CACf,OAAO,CACL,KAAK,CbgD6B,OAAwB,Ca/C5D,SAAS,CACP,KAAK,Cb6C6B,OAAO,CanB7C,IAAI,CACF,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,MAAM,CAEpB,IAAI,CACF,WAAW,CX3CyB,uDAAM,CW4C1C,WAAW,CAAE,MAAM,CACnB,KAAK,CX/C+B,OAAW,CWgD/C,UAAU,CAAE,IAAI,CAChB,UAAU,CAAE,MAAM,CAClB,UAAU,CbnD0B,OAAO,CaqD7C,aAAa,CACX,UAAU,CAAE,IAAI,CAElB,eAAe,CACb,UAAU,CAAE,MAAM,CAEpB,cAAc,CACZ,UAAU,CAAE,KAAK,CAEnB,cAAc,CACZ,SAAS,CAAE,IAAI,CAEjB,eAAe,CACb,SAAS,CAAE,IAAI,CAEjB,oBAAqB,CACnB,SAAS,CAAE,GAAG,CAEhB,eAAe,CACb,eAAe,CAAE,YAAY,CAE/B,gBAAgB,CACd,KAAK,CAAE,kBAAkB,CAC3B,uBAAuB,CACrB,KAAK,CAAE,kBAAgC,CACzC,aAAa,CACX,KAAK,CAAE,kBAAgB,CACzB,oBAAoB,CAClB,KAAK,CAAE,kBAA8B,CACvC,gBAAgB,CACd,KAAK,CAAE,kBAAiB,CAC1B,uBAAuB,CACrB,KAAK,CAAE,kBAA+B,CACxC,eAAe,CACb,KAAK,CAAE,kBAAe,CACxB,sBAAsB,CACpB,KAAK,CAAE,kBAA6B,CACtC,gBAAgB,CACd,KAAK,CAAE,kBAAsB,CAC/B,uBAAuB,CACrB,KAAK,CAAE,kBAAoC,CAkB7C,gEAAyB,CACvB,UAAU,CAAE,CAAC,CACb,WAAW,CAAE,GAAG,CAChB,WAAW,CX9GyB,0DAAa,CWgHnD,CAAC,CACC,WAAW,Cb1FyB,IAAI,Ca2FxC,MAAM,CAAE,CAAC,CACT,SAAS,Cb/F2B,IAAI,CagGxC,aAAa,Cb7FuB,IAAI,Ca+F1C,EAAE,CACA,SAAS,CAAE,IAAI,CAEjB,0CAAE,CACA,SAAS,CAAE,IAAI,CAEjB,EAAE,CACA,SAAS,CAAE,IAAI,CAEjB,EAAE,CACA,SAAS,CAAE,IAAI,CAEjB,EAAE,CACA,SAAS,CAAE,IAAI,CAEjB,EAAE,CACA,SAAS,CAAE,IAAI,CAEjB,EAAE,CACA,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,GAAG,CACX,MAAM,CAAE,CAAC,CACT,UAAU,CAAE,iBAA6B,CACzC,MAAM,CAAE,MAAmB,CAC3B,OAAO,CAAE,CAAC,CAEZ,sCAAI,CACF,WAAW,CAAE,MAAM,CACnB,SAAS,CAAE,IAAI,CACf,UAAU,CblG0B,IAAM,CamG1C,MAAM,CAAE,iBAAiC,CACzC,SAAS,CAAE,GAAG,CACd,OAAO,CAAE,KAAK,CACd,WAAW,CXrJyB,wMAAQ,CWsJ5C,KAAK,Cb1H+B,OAAI,Ca2HxC,UAAU,CAAE,IAAI,CAChB,0CAAY,CACV,SAAS,CAAE,GAAG,CAmClB,wFAAmB,CACjB,UAAU,CAAE,IAAI,CAChB,WAAW,CbzKyB,IAAI,Ca0KxC,aAAa,Cb1KuB,IAAI,Ca2KxC,oGAAE,CACA,UAAU,CAAE,IAAI,CAChB,WAAW,Cb7KuB,IAAI,Ca8KtC,wJAAY,CACV,aAAa,CAAE,CAAC,CAClB,gHAAE,CACA,aAAa,CAAE,CAAC,CAClB,gHAAE,CACA,UAAU,CAAE,MAAM,CAClB,4HAAE,CACA,UAAU,CAAE,MAAM,CACtB,4HAAK,CACH,UAAU,CAAE,OAAO,CAEzB,iFAAsB,CACpB,UAAU,CAAE,OAAO,CACnB,WAAW,Cb3LyB,IAAI,Ca4LxC,aAAa,Cb5LuB,IAAI,Ca6LxC,6FAAE,CACA,UAAU,CAAE,OAAO,CACnB,WAAW,Cb/LuB,IAAI,CagMtC,iJAAY,CACV,aAAa,CAAE,CAAC,CAClB,yGAAE,CACA,aAAa,CAAE,CAAC,CAChB,qHAAE,CACA,UAAU,CAAE,IAAI,CCrOxB,kBAAkB,CAChB,MAAM,CAAE,iBAA6B,CACrC,aAAa,CAAE,IAAI,CACnB,OAAO,Cd6B6B,IAAI,Cc5BxC,WAAW,CAAE,IAAqB,CAClC,WAAW,CAAE,GAAG,CAChB,UAAU,CdoD0B,IAAM,CcnD1C,QAAQ,CAAE,QAAQ,CAClB,wBAAO,CACL,OAAO,CAAE,SAAS,CAClB,QAAQ,CAAE,QAAQ,CAClB,GAAG,CAAE,GAAG,CACR,IAAI,CAAE,GAAG,CACT,UAAU,CdoDwB,OAAO,CcnDzC,KAAK,CAAE,IAAoB,CAC3B,OAAO,CAAE,QAA2C,CACtD,2CAA0B,CACxB,MAAM,CAAE,iBAA6B,CACrC,aAAa,CdcqB,IAAI,CcZ1C,+GAAmC,CACjC,MAAM,CAAE,iBAA6B,CACrC,OAAO,CAAE,GAAG,CACZ,UAAU,CAAE,IAAI,CAChB,UAAU,CdkC0B,IAAM,CchC1C,MAAM,CAAE,YAAyB,CACjC,gLAAuB,CACrB,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,IAAI,CAChB,MAAM,CAAE,CAAC,CAEb,+BAA+B,CAC7B,KAAK,CAAE,IAAI,CACb,cAAc,CACZ,YAAY,CAAE,iBAA0C,CACxD,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,SAA2C,CACpD,WAAW,CZ3ByB,wMAAQ,CY4B5C,SAAS,CAAE,IAAI,CACf,WAAW,CAAE,GAAG,CAChB,KAAK,CdI+B,OAAwB,CcH9D,2BAA2B,CACzB,WAAW,CAAE,GAAG,CAChB,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,SAA2C,CACpD,WAAW,CZnCyB,wMAAQ,CYoC5C,SAAS,CAAE,IAAI,CACf,WAAW,CAAE,GAAG,CAChB,OAAO,CAAE,KAAK,CACd,QAAQ,CAAE,IAAI,CACd,KAAK,CZ7C+B,OAAW,CYiDjD,YAAY,CACV,2IAAgE,CAC9D,WAAW,CAAE,QAAQ,ECzDzB,IAAI,CACF,gBAAgB,CAAE,IAAO,CACzB,MAAM,CAAE,OAAO,CACf,OAAO,CAAE,MAAM,CACf,OAAO,CAAE,KAAK,CAChB,EAAE,CACA,KAAK,CAAE,IAAO,CACd,UAAU,CAAE,MAAM,CACpB,IAAI,CACF,KAAK,CAAE,OAAO,CACd,gBAAgB,CAAE,OAAO,CAC3B,EAAE,CACA,WAAW,CAAE,IAAI,CACnB,EAAE,CACA,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,KAAK,CAAE,IAAO,CACd,UAAU,CAAE,MAAM,CACpB,GAAG,CACD,KAAK,CAAE,IAAO,CACd,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,KAAK,CAAE,IAAO,CACd,UAAU,CAAE,MAAM,CACpB,GAAG,CACD,KAAK,CAAE,IAAO,CACd,WAAW,CAAE,IAAI,CACjB,UAAU,CAAE,MAAM,CACpB,GAAG,CACD,KAAK,CAAE,IAAO,CACd,gBAAgB,CAAE,IAAO,CAC3B,MAAM,CACJ,KAAK,CAAE,IAAO,CACd,gBAAgB,CAAE,IAAO,CAC3B,GAAG,CACD,UAAU,CAAE,MAAM,CACpB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CACd,gBAAgB,CAAE,IAAO,CAC3B,MAAM,CACJ,KAAK,CAAE,IAAO,CACd,gBAAgB,CAAE,IAAO,CAC3B,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,KAAK,CAAE,MAAO,CACd,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,KAAK,CAAE,IAAO,CACd,WAAW,CAAE,IAAI,CACnB,EAAE,CACA,KAAK,CAAE,IAAO,CAChB,EAAE,CACA,KAAK,CAAE,IAAO,CAChB,EAAE,CACA,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAI,CACb,GAAG,CACD,KAAK,CAAE,OAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CACd,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,KAAK,CAAE,IAAI,CACb,GAAG,CACD,KAAK,CAAE,MAAM,CACf,GAAG,CACD,KAAK,CAAE,IAAO,CACd,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,KAAK,CAAE,IAAO,CACd,WAAW,CAAE,IAAI,CACnB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAI,CACb,GAAG,CACD,KAAK,CAAE,IAAI,CACb,GAAG,CACD,WAAW,CAAE,IAAI,CACnB,EAAE,CACA,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,OAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,OAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAI,CACb,GAAG,CACD,KAAK,CAAE,IAAI,CACb,GAAG,CACD,KAAK,CAAE,IAAI,CACb,GAAG,CACD,KAAK,CAAE,IAAO,CAChB,GAAG,CACD,KAAK,CAAE,IAAI,CACX,gBAAgB,CAAE,OAAO,CCjJ3B,kBAAkB,CAChB,OAAO,CAAE,YAAY,CACrB,uCAAsB,CACpB,KAAK,CAAE,KAAK,CACd,oBAAC,CACC,OAAO,CAAE,YAAY,CACrB,OAAO,CAAE,GAAG,CACZ,gCAAa,CACX,YAAY,CAAE,CAAC,CACnB,6FAAI,CACF,OAAO,CAAE,GAAG,CACZ,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,IAAI,CAChB,qHAAS,CACP,KAAK,CdR2B,OAAW,CcSjD,qBAAqB,CACnB,aAAa,CAAE,CAAC,CAChB,KAAK,ChB2B+B,OAAwB,CgB1B5D,SAAS,CAAE,GAAG,CACd,OAAO,CAAE,YAAY,CbanB,oCAAsB,CaTxB,qBAAqB,CACnB,OAAO,CAAE,IAAI,CACf,uCAAuC,CACrC,OAAO,CAAE,IAAI,EAEjB,YAAY,CACV,uCAAuC,CACrC,OAAO,CAAE,IAAI,EC9BjB,SAAS,CACP,QAAQ,CAAE,KAAK,CACf,GAAG,CCAO,OAAO,CDGjB,gBAAO,CACL,eAAe,CAAE,IAAI,CAEzB,cAAc,C/B+FZ,KAAK,CAAE,CAAC,CACR,0CAAS,CAEP,OAAO,CAAE,KAAK,CACd,OAAO,CAAE,EAAE,CACb,oBAAO,CACL,KAAK,CAAE,IAAI,C+BnGb,mCAAM,CACJ,OAAO,CAAE,YAAY,CACvB,uBAAQ,CACN,UAAU,CAAE,qBAAoB,CAEhC,6BAAa,CACX,WAAW,CAAE,iBAAyB,CACxC,8BAAc,CACZ,YAAY,CAAE,iBAAyB,CAC3C,gBAAC,CACC,MAAM,CAAE,IAAmB,CAC3B,OAAO,CAAE,YAAY,CACrB,WAAW,CAAE,IAAmB,CAChC,OAAO,CAAE,MAAiB,CAG5B,oDAAiB,CACf,MAAM,CAAE,IAAmB,CAC3B,OAAO,CAAE,YAAY,CACrB,WAAW,CAAE,IAAmB,CAChC,OAAO,CAAE,SAAS,CAClB,aAAa,CAAE,CAAC,CAChB,OAAO,CAAE,KAAK,CACd,WAAW,CAAE,IAAI,CACjB,cAAc,CAAE,SAAS,CACzB,SAAS,CAAE,GAAG,CACd,KAAK,CjBvB6B,IAAI,CiBwBtC,WAAW,CAAE,MAAM,CAErB,oBAAE,CACA,aAAa,CAAE,CAAC,CAEhB,+BAAY,CACV,UAAU,CAAE,iBAAyB,CACvC,kCAAe,CACb,aAAa,CAAE,iBAAyB,CAC1C,4BAAS,CACP,UAAU,CAAE,OAAsC,CAClD,8BAAC,CACC,KAAK,CjBNyB,IAAwB,CiBOtD,YAAY,CAAE,iBAAgD,CAC9D,OAAO,CAAE,gBAAyB,CAClC,oCAAO,CACL,UAAU,CAAE,OAAsC,CACxD,mGAAI,CACF,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,OAAO,CACnB,KAAK,CAAE,OAAO,CACd,YAAY,CAAE,CAAC,CACf,aAAa,CAAE,CAAC,CAElB,wCAAmB,CACjB,OAAO,CAAE,KAAK,CACd,KAAK,CAAE,IAAI,CACX,WAAW,CAAE,MAAM,CAGnB,SAAS,CAAE,KAAI,CACf,WAAW,CAAE,KAAK,CAClB,KAAK,CAAE,OAAyB,CAGpC,wDAAuB,CACrB,KAAK,CfnE6B,OAAW,CeoE7C,OAAO,CAAE,gBAAmB,CAC5B,WAAW,CAAE,IAAI,CACjB,QAAQ,CAAE,QAAQ,CAClB,UAAU,CjBtEwB,OAAyB,CiBuE3D,MAAM,CAAE,IAAI,CACZ,aAAa,CAAE,iBAAgD,CAC/D,UAAU,CAAE,iBAAgD,CAC5D,YAAY,CAAE,YAAY,CAE1B,oEAAO,CACL,UAAU,CjB7EsB,OAAyB,CiB8EzD,4GAAmB,CACjB,KAAK,CjB3CyB,IAAwB,CiB4C1D,gGAAmB,CAGjB,OAAO,CAAE,KAAK,CACd,SAAS,CAAE,KAAI,CACf,WAAW,CAAE,KAAK,CAClB,KAAK,CAAE,IAAyB,CAIlC,iHAAI,CACF,OAAO,CAAE,IAAI,CACf,iIAAc,CACZ,OAAO,CAAE,KAAK,CAGd,yCAAG,CACD,UAAU,CAAE,OAAsC,CAClD,OAAO,CAAE,gBAAyB,CACpC,uDAAiB,CACf,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,OAAsC,CAClD,OAAO,CAAE,gBAAyB,CACtC,2DAA2B,CACzB,KAAK,CjBpE2B,IAAwB,CiBqE1D,mDAAmB,CACjB,KAAK,CAAE,OAAsC,CACjD,+BAAa,CACX,SAAS,CAAE,KAAI,CAEb,yCAAG,CACD,UAAU,CAAE,OAAsC,CAClD,OAAO,CAAE,gBAAyB,CACpC,uDAAiB,CACf,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,OAAsC,CAClD,OAAO,CAAE,gBAAyB,CAClC,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,IAAI,CACvB,2DAA2B,CACzB,KAAK,CjBpF2B,IAAwB,CiBqF1D,mDAAmB,CACjB,KAAK,CAAE,OAAsC,CACjD,+BAAa,CACX,SAAS,CAAE,KAAI,CAEjB,+BAAa,CACX,OAAO,CAAE,KAAK,CAChB,uBAAK,CACH,aAAa,CAAE,CAAC,CAChB,OAAO,CAAE,IAAI,CAEb,kCAAK,CACH,OAAO,CAAE,KAAK,CAClB,4BAAU,CACR,aAAa,CAAE,CAAC,CAChB,KAAK,CjBnG6B,OAAwB,CiBoG1D,WAAW,CAAE,MAAM,CACrB,mBAAC,CACC,OAAO,CAAE,YAAY,CACrB,WAAW,CAAE,IAAI,CACjB,OAAO,CAAE,gBAAmB,CAC5B,OAAO,CAAE,KAAK,CACd,QAAQ,CAAE,QAAQ,CAClB,SAAS,CAAE,GAAG,CACd,KAAK,CjB5G6B,OAAwB,CiB6G1D,yBAAO,CACL,gBAAgB,CAAE,OAAoC,CACtD,MAAM,CAAE,OAAO,CACf,6CAAmB,CACjB,KAAK,CjBjHyB,OAAwB,CiBkH1D,0BAAQ,CACN,gBAAgB,CjB/EgB,OAAW,CiBgF3C,MAAM,CAAE,OAAO,CACf,KAAK,CjBvG2B,IAAM,CiBwGtC,8CAAmB,CACjB,KAAK,CjBzGyB,IAAM,CiB2G5C,mBAAmB,CACjB,OAAO,CjBhF6B,GAAG,CiBiFvC,gBAAgB,CjBvFoB,OAAW,CiBwF/C,UAAU,CAAE,MAAM,CAClB,OAAO,CAAE,OAAW,CACpB,OAAO,CAAE,KAAK,CACd,KAAK,CjBpK+B,OAAyB,CiBqK7D,aAAa,CAAE,OAAW,CAC1B,oCAAgB,CACd,KAAK,CAAE,IAAI,CACX,aAAa,CAAE,IAAI,CACnB,OAAO,CAAE,QAAQ,CACjB,YAAY,CAAE,OAAuB,CACvC,uBAAG,CACD,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,sBAA0B,CAClC,MAAM,CAAE,IAAI,CACZ,KAAK,CAAE,IAAI,CACX,gBAAgB,CjBvGkB,OAAW,CiBwG7C,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAI,CACrB,wDAAqB,CACnB,KAAK,CjBpL6B,OAAyB,CiBqL3D,SAAS,CAAE,IAAI,CACf,WAAW,CAAE,IAAI,CACjB,OAAO,CAAE,YAAY,CACrB,OAAO,CAAE,OAA2C,CACpD,aAAa,CAAE,OAAW,CAE1B,oEAAO,CACL,UAAU,CAAE,qBAAoB,CAClC,0EAAQ,CACN,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,MAAM,CACd,MAAM,CAAE,IAAI,CACZ,KAAK,CAAE,IAAI,CACX,aAAa,CAAE,CAAC,CAChB,SAAS,CAAE,IAAI,CACf,UAAU,CAAE,WAAa,CAEzB,oFAAQ,CACN,UAAU,CAAE,MAAM,CACxB,+BAAa,CACX,UAAU,CAAE,SAAkB,CAC9B,aAAa,CAAE,OAAW,CAC1B,WAAW,CAAE,MAAM,CACnB,KAAK,CAAE,qBAAoB,CAI7B,gCAAM,CACJ,KAAK,CjBxI6B,OAAW,CiByI/C,2BAAC,CACC,KAAK,CjB9K6B,OAAwB,CiB+K1D,iCAAO,CACL,gBAAgB,CjB5IgB,OAAW,CiB6I3C,KAAK,CjBnK2B,IAAM,CiBqK5C,gBAAgB,CjCtNR,kBAAoB,CAAE,gBAAM,CAK5B,eAAiB,CAAE,gBAAM,CAezB,UAAY,CAAE,gBAAM,CiCoM1B,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,CAAC,CACV,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,CAAC,CACV,4BAAa,CACX,IAAI,CAAE,CAAC,CACP,KAAK,CAAE,IAAI,CACX,OAAO,CAAE,CAAC,CACZ,0BAAW,CACT,KAAK,CAAE,IAAI,CACX,IAAI,CAAE,KAAK,CACX,OAAO,CAAE,CAAC,CACZ,2BAAY,CACV,KAAK,CAAE,KAAK,CACZ,IAAI,CAAE,IAAI,CACV,OAAO,CAAE,CAAC,CAGd,gBAAgB,CACd,UAAU,CAAE,qBAAuC,CACnD,gBAAgB,CAAE,2uCAA2uC,CAC7vC,eAAe,CAAE,SAAsB,CAEzC,gBAAgB,CACd,QAAQ,CAAE,QAAQ,CAClB,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CAEd,YAAY,CACV,QAAQ,CAAE,KAAK,CACf,GAAG,CAAE,CAAC,CACN,MAAM,CAAE,CAAC,CACT,IAAI,CAAE,CAAC,CACP,cAAc,CAAE,GAAG,CACnB,KAAK,CjBlL+B,KAAK,CiBmLzC,UAAU,CAAE,MAAM,CAClB,UAAU,CAAE,MAAM,CAClB,UAAU,CAAE,IAAI,CAChB,UAAU,CjBxLsB,OAAe,CiByL/C,OAAO,CjBlL6B,GAAG,CiBoLzC,WAAW,CACT,OAAO,CAAE,IAAI,CACb,UAAU,CjB5L0B,OAAW,CiB6L/C,KAAK,CjBnN+B,IAAM,CiBoN1C,OAAO,CAAE,gBAAuB,CAChC,QAAQ,CAAE,QAAQ,CAClB,WAAW,CAAE,IAAI,CACjB,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,IAAI,C/B3Kf,KAAK,CAAE,CAAC,CACR,oCAAS,CAEP,OAAO,CAAE,KAAK,CACd,OAAO,CAAE,EAAE,CACb,iBAAO,CACL,KAAK,CAAE,IAAI,C+BuKb,aAAC,CACC,KAAK,CjB3N6B,IAAM,CiB4NxC,WAAW,CAAE,IAAI,CAEnB,eAAG,CACD,YAAY,CAAE,IAAqB,CACnC,MAAM,CAAE,IAAI,CACZ,KAAK,CAAE,IAAI,CACX,gBAAgB,CjB5MkB,OAAW,CiB6M7C,OAAO,CAAE,GAAG,CACZ,aAAa,CAAE,IAAI,CACrB,aAAC,CACC,SAAS,CAAE,IAAI,CACf,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,OAAO,CAEnB,oBAAoB,CAClB,WAAW,CjBpNyB,KAAK,CiBqNzC,UAAU,CjB/R0B,OAAyB,CiBgS7D,UAAU,CAAE,IAAI,CAElB,eAAe,CACb,OAAO,CAAE,eAAmB,CAC5B,MAAM,CAAE,IAAI,CACZ,SAAS,CAAE,KAAK,CAChB,MAAM,CAAE,IAAI,CAEd,aAAa,CACX,QAAQ,CAAE,KAAK,CACf,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,eAAc,CAC1B,OAAO,CAAE,IAAI,CACb,OAAO,CAAE,GAAkB,CAC3B,gBAAI,CACF,OAAO,CAAE,KAAK,CAClB,MAAM,CACJ,KAAK,CjB3S+B,IAAI,CiB4SxC,QAAC,CACC,aAAa,CAAE,IAAqB,CACtC,6FAAgB,CACd,OAAO,CAAE,GAAG,CACZ,WAAW,CfnTuB,wMAAQ,CeoT1C,SAAS,CAAE,GAAG,CACd,UAAU,CAAE,IAAI,CAChB,MAAM,CAAE,IAAI,CACZ,KAAK,CjBpT6B,IAAI,CiBsT1C,mBAAmB,C/B7NjB,KAAK,CAAE,CAAC,CACR,oDAAS,CAEP,OAAO,CAAE,KAAK,CACd,OAAO,CAAE,EAAE,CACb,yBAAO,CACL,KAAK,CAAE,IAAI,C+B2Nb,0BAAU,CACR,aAAa,CjBzSqB,IAAI,CiB0StC,aAAa,CAAE,iBAA6B,CAC5C,cAAc,CjB3SoB,IAAI,CiB4SxC,sCAAsB,CACpB,UAAU,CAAE,iBAA6B,CACzC,WAAW,CjB9SuB,IAAI,CiB+SxC,4BAAY,CACV,SAAS,CAAE,IAAI,CACf,aAAa,CAAE,IAAqB,CACpC,OAAO,CAAE,YAAY,CACvB,wBAAQ,CACN,KAAK,CjBzS6B,IAAwB,CiB0S1D,SAAS,CAAE,GAAG,CdrTd,oCAAsB,CcyTxB,gBAAgB,CACd,UAAU,CjBnVwB,OAAyB,CiBoV7D,WAAW,CACT,OAAO,CAAE,KAAK,CAChB,YAAY,CAER,IAAI,CAAE,MAAmB,CAG3B,kBAAO,CACL,KAAK,CAAE,GAAG,CACV,IAAI,CAAE,CAAC,CACX,oBAAoB,CAClB,WAAW,CAAE,CAAC,CACd,oCAAe,CACb,OAAO,CCtWD,OAAO,CDuWf,0BAAO,CACL,QAAQ,CAAE,KAAK,CACf,SAAS,CAAE,IAAI,CACf,IAAI,CAAE,GAAG,CACT,GAAG,CAAE,CAAC,CACN,MAAM,CAAE,IAAI,CACZ,QAAQ,CAAE,MAAM,Ed/UlB,qCAAsB,CckVxB,oBAAoB,CAClB,UAAU,CAAE,gBAAe,CAC7B,eAAe,CACb,MAAM,CAAE,CAAC,CACT,UAAU,CjB/WwB,OAAyB,EiBiX/D,YAAY,CACV,iCAAmC,CACjC,OAAO,CAAE,IAAI,CACf,oBAAoB,CAClB,WAAW,CAAE,CAAC,EE5XlB,aAAa,CACX,QAAQ,CAAE,KAAK,CACf,MAAM,CAAE,CAAC,CACT,IAAI,CAAE,CAAC,CACP,KAAK,CnB6E+B,KAAK,CmB5EzC,KAAK,CnBE+B,OAAyB,CmBD7D,UAAU,CAAE,OAAkC,CAC9C,UAAU,CAAE,kBAAiC,CAC7C,WAAW,CjBAyB,uDAAM,CiBC1C,OAAO,CnB+E6B,GAAG,CmB9EvC,eAAC,CACC,KAAK,CnBqE6B,OAAW,CmBpE7C,eAAe,CAAE,IAAI,CACvB,8BAAgB,CACd,OAAO,CAAE,IAAI,CACf,kCAAoB,CAClB,OAAO,CAAE,IAAqB,CAC9B,gBAAgB,CAAE,OAAkC,CACpD,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,KAAK,CACjB,SAAS,CAAE,GAAG,CACd,MAAM,CAAE,OAAO,CACf,KAAK,CnBiD6B,OAAM,CdgC1C,KAAK,CAAE,CAAC,CACR,kFAAS,CAEP,OAAO,CAAE,KAAK,CACd,OAAO,CAAE,EAAE,CACb,wCAAO,CACL,KAAK,CAAE,IAAI,CiCrFX,uqDAAG,CACD,KAAK,CnBlB2B,OAAyB,CmBmB3D,yFAAQ,CACN,KAAK,CAAE,IAAI,CACb,6CAAU,CACR,KAAK,CAAE,IAAI,CACb,kDAAiB,CACf,gBAAgB,CnBQgB,OAAI,CmBPpC,KAAK,CnB0B2B,IAAM,CmBzBxC,yDAAwB,CACtB,gBAAgB,CnBXgB,OAAO,CmBYvC,KAAK,CnBzB2B,IAAI,CmB0BxC,0CAA8B,CAC5B,OAAO,CAAE,KAAK,CAChB,iCAAmB,CACjB,SAAS,CAAE,GAAG,CACd,OAAO,CAAE,IAAqB,CAC9B,KAAK,CnBE6B,IAAwB,CmBD1D,OAAO,CAAE,IAAI,CACb,oCAAE,CACA,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,GAAG,CACX,MAAM,CAAE,CAAC,CACT,MAAM,CAAE,MAAM,CACd,OAAO,CAAE,CAAC,CACV,UAAU,CAAE,iBAA6C,CAC3D,oCAAE,CACA,OAAO,CAAE,YAAY,CACrB,MAAM,CAAE,CAAC,CACT,sCAAC,CACC,OAAO,CAAE,YAAY,CACrB,OAAO,CAAE,GAAqB,CAC9B,KAAK,CnBjDyB,OAAyB,CmBkD7D,uBAAW,CACT,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,KAAK,CAAE,IAAI,CACX,IAAI,CAAE,IAAI,CACV,MAAM,CAAE,IAAI,CACZ,SAAS,CnBkByB,KAAK,CmBjBvC,kCAAU,CACR,KAAK,CAAE,IAAI,CACb,mEAAQ,CACN,KAAK,CAAE,IAAI,CACb,qDAA+B,CAC7B,UAAU,CAAE,KAAK,CACjB,+HAAQ,CACN,KAAK,CAAE,IAAI,CACb,gEAAU,CACR,KAAK,CAAE,IAAI,CACf,4CAAoB,CAClB,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,WAAW,CAAE,IAAI,CACjB,OAAO,CAAE,KAAuB,CAChC,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,MAAM,ChBhDpB,oCAAsB,CgBmDxB,aAAa,CACX,KAAK,CAAE,GAAG,CACV,OAAO,CAAE,IAAI,CACb,mBAAO,CACL,OAAO,CAAE,KAAK,CAClB,GAAG,CACD,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,ECzEd,gBAAG,CACD,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,eAAe,CAEzB,uBAAU,CACR,aAAa,CpBUqB,IAAI,CoBTtC,iCAAS,CACP,UAAU,CAAE,MAAM,CAEtB,oCAAuB,CACrB,UAAU,CAAE,MAAM,CAGpB,qDAAoC,CAClC,aAAa,CpBCqB,IAAI,CoBUxC,uBAAU,CACR,WAAW,CpBXuB,IAAI,CoBYtC,WAAW,CpBZuB,IAAI,CoBatC,aAAa,CpBbqB,IAAI,CoBmBtC,kTAAK,CACH,aAAa,CAAE,CAAC,CAKlB,qCAAQ,CACN,YAAY,CAAE,GAAG,CAUrB,8BAAiB,CACf,YAAY,CAAE,eAAc,CAC5B,mEAAM,CACJ,UAAU,CAAE,sBAAsB,CAClC,YAAY,CAAE,0BAAyB,CAG3C,0EAAiD,CAC/C,UAAU,CAAE,WAAW,CACzB,0EAAiD,CAC/C,UAAU,CAAE,WAAW,CAGzB,qDAA4B,CAC1B,aAAa,CAAE,IAAqB,CACtC,wBAAW,CACT,WAAW,CpBpDuB,IAAI,CoBuDxC,yBAAY,CACV,WAAW,CAAE,IAAI,CACjB,aAAa,CAAE,IAAqB,CACtC,yBAAY,CACV,KAAK,ClBrF6B,OAAW,CkBsF/C,yBAAY,CACV,KAAK,CAAE,KAAK,CACZ,MAAM,CAAE,iBAA2C,CACrD,wBAAW,CACT,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,iBAA2C,CACrD,0BAAa,CACX,MAAM,CAAE,IAAI,CACZ,OAAO,CAAE,KAAK,CAMd,6RAAW,CACT,OAAO,CAAE,IAAI,CACb,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,IAAI,CAEf,mVAAO,CACL,UAAU,CAAE,OAAO,CACnB,OAAO,CAAE,GAAO,CAChB,WAAW,CAAE,WAAW,CACxB,OAAO,CAAE,YAAY,CACzB,mVAAmB,CACjB,OAAO,CAAE,YAAY,CAGzB,qBAAQ,CACN,KAAK,CAAE,KAAK,CACZ,KAAK,CAAE,GAAG,CACV,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,aAAuC,CAC/C,OAAO,CpB7F2B,IAAI,CoB8FtC,UAAU,CpBtDwB,OAAmB,CoBuDrD,MAAM,CAAE,iBAA6B,CAErC,yEAAS,CACP,SAAS,CAAE,GAAG,CAChB,2BAAK,CACH,aAAa,CAAE,CAAC,CAClB,oCAAc,CACZ,OAAO,CAAE,KAAK,CACd,WAAW,ClB9HqB,0DAAa,CkB+H7C,WAAW,CAAE,IAAI,CACjB,UAAU,CpBrFsB,OAAmB,CoBsFnD,OAAO,CAAE,QAA2C,CACpD,MAAM,CAAE,KAAkB,CAC1B,aAAa,CpB5GmB,IAAI,CoB6GpC,SAAS,CAAE,IAAI,CAEnB,yBAAY,CACV,UAAU,CpBzHwB,OAAO,CoB0HzC,OAAO,CAAE,YAAY,CACrB,WAAW,CAAE,IAAI,CACjB,OAAO,CAAE,KAAuB,CAGlC,iEAAwC,CACtC,cAAc,CAAE,KAAK,CACrB,SAAS,CAAE,GAAG,CAIhB,yEAAgD,CAC9C,UAAU,CAAE,IAAI,CAChB,MAAM,CAAE,IAAI,CACZ,KAAK,CpBjJ6B,IAAI,CoBkJtC,+JAAM,CACJ,MAAM,CAAE,IAAI,CACZ,gBAAgB,CAAE,sBAAsB,CACxC,WAAW,CAAE,MAAM,CACrB,2FAAQ,CACN,YAAY,CAAE,CAAC,CACf,aAAa,CAAE,CAAC,CAChB,cAAc,CAAE,GAAG,CACrB,mKAAI,CACF,KAAK,CpB5J2B,IAAI,CoBmKxC,6BAAgB,CAEd,MAAM,CAAE,IAAI,CACZ,gCAAE,CACA,MAAM,CAAE,IAAI,CACZ,WAAW,CAAE,GAAG,CAClB,uCAAW,CACT,OAAO,CAAE,YAAY,CACrB,UAAU,CAAE,GAAG,CACjB,yCAAW,CACT,aAAa,CAAE,IAAI,CACnB,UAAU,CAAE,IAAI,CAChB,WAAW,CAAE,MAAM,CACrB,yCAAW,CACT,UAAU,CAAE,IAAI,CAChB,YAAY,CAAE,CAAC,CAGnB,iDAAQ,CAEN,KAAK,CpB1L6B,IAAI,CoB2LtC,wHAAO,CACL,SAAS,CAAE,eAAe,CAC1B,WAAW,CAAE,MAAM,CAErB,yEAAS,CACP,KAAK,CpBnK2B,OAAI,CoBoKtC,wHAAW,CACT,WAAW,CAAE,IAAI,CACjB,KAAK,ClBvM2B,OAAW,CkByM/C,uDAAY,CACV,KAAK,CpBhI6B,OAAW,CoBiI/C,eAAE,CACA,aAAa,CpBlLqB,IAAI,CoBmLtC,kBAAE,CACA,WAAW,CAAE,IAAI,CAEnB,6EAAgB,CACd,aAAa,CAAE,eAAgC,CAEjD,kBAAE,CACA,MAAM,CAAE,aAA4C,CAMxD,8BAAiB,CACf,aAAa,CpBjMqB,IAAI,CoBmMtC,iCAAE,CACA,OAAO,CAAE,YAAY,CACrB,MAAM,CAAE,KAAuB,CAC/B,SAAS,CAAE,GAAG,CACd,WAAW,CAAE,MAAM,CACnB,UAAU,CAAE,OAAmB,CAC/B,KAAK,CpBzJ2B,OAAW,CoB0J3C,UAAU,CAAE,iBAA6B,CACzC,OAAO,CAAE,GAAqB,CAC9B,QAAQ,CAAE,QAAQ,CAClB,wCAAQ,CACN,KAAK,CAAE,OAAmB,CAC5B,6CAAW,CACT,KAAK,ClB1OyB,OAAW,CkB2OzC,SAAS,CAAE,eAAe,CAE9B,oCAAK,CACH,aAAa,CAAE,GAAqB,CACpC,MAAM,CAAE,IAAI,CACZ,WAAW,CAAE,cAAuB,CACpC,UAAU,CAAE,OAAa,CACzB,KAAK,CpB7M2B,IAAwB,CoB8MxD,gDAAW,CACT,KAAK,ClBpPyB,OAAW,CkBqPzC,SAAS,CAAE,eAAe,CAC9B,6CAAc,CACZ,UAAU,CAAE,CAAC,CAEf,uGAAQ,CACN,WAAW,CAAE,IAAI,CACjB,oRAA2B,CACzB,gBAAgB,CAAE,WAAW,CAC7B,MAAM,CAAE,IAAI,CACZ,OAAO,CAAE,CAAC,CACV,SAAS,CAAE,eAAe,CAC5B,kIAAU,CACR,WAAW,CAAE,IAAI,CAErB,wCAAS,CACP,OAAO,CAAE,YAAY,CACrB,OAAO,CAAE,KAAK,CACd,KAAK,CpBlQ2B,IAAI,CoBmQpC,WAAW,CAAE,IAAI,CACnB,wCAAS,CACP,OAAO,CAAE,YAAY,CACrB,aAAa,CAAE,GAAG,CAEtB,uDAA8B,CAC5B,OAAO,CAAE,YAAY,CACrB,KAAK,CpB7M6B,OAAM,CoB8MxC,SAAS,CAAE,GAAG,CACd,YAAY,CpBtPsB,IAAI,CoBuPxC,2BAAc,CACZ,OAAO,CAAE,KAAK,CACd,KAAK,CAAE,KAAK,CACd,qBAAQ,CACN,aAAa,CAAE,IAAI,CACnB,WAAW,CAAE,IAAI,CAEnB,mDAAa,CACX,UAAU,CAAE,OAAO,CACnB,OAAO,CAAE,OAAO,CAChB,WAAW,CAAE,OAAO,CACpB,SAAS,CAAE,OAAO,CAClB,KAAK,CAAE,OAAO,CACd,MAAM,CAAE,OAAO,CACf,WAAW,CAAE,OAAO,CAIlB,mGAAQ,CACN,YAAY,CAAE,GAAG,CjB1QrB,oCAAsB,CiB+QtB,qBAAQ,CACN,KAAK,CAAE,IAAI,EChTjB,wBAAwB,CACtB,KAAK,CnBK+B,OAAW,CmBHjD,KAAK,CACH,UAAU,CAAE,MAAM,YCHlB,WAAW,CAAE,aAAa,CAC1B,UAAU,CAAE,MAAM,CAClB,WAAW,CAAE,GAAG,CAChB,GAAG,CAAE,qEAAoB,YAGzB,WAAW,CAAE,aAAa,CAC1B,UAAU,CAAE,MAAM,CAClB,WAAW,CAAE,GAAG,CAChB,GAAG,CAAE,yGAAyB,YAG9B,WAAW,CAAE,MAAM,CACnB,UAAU,CAAE,MAAM,CAClB,WAAW,CAAE,GAAG,CAChB,GAAG,CAAE,6FAAqB,YAG1B,WAAW,CAAE,MAAM,CACnB,UAAU,CAAE,MAAM,CAClB,WAAW,CAAE,GAAG,CAChB,GAAG,CAAE,oFAAkB,YAGvB,WAAW,CAAE,aAAa,CAC1B,UAAU,CAAE,MAAM,CAClB,WAAW,CAAE,GAAG,CAChB,GAAG,CAAE,gHAA4B,YAGjC,WAAW,CAAE,aAAa,CAC1B,UAAU,CAAE,MAAM,CAClB,WAAW,CAAE,GAAG,CAChB,GAAG,CAAE,uGAAyB", +"sources": ["../../../bower_components/neat/app/assets/stylesheets/grid/_grid.scss","../../../bower_components/bourbon/dist/addons/_prefixer.scss","../../../bower_components/wyrm/sass/wyrm_core/_reset.sass","../../../bower_components/wyrm/sass/wyrm_core/_mixin.sass","../../../bower_components/font-awesome/scss/_path.scss","../../../bower_components/font-awesome/scss/_core.scss","../../../bower_components/font-awesome/scss/_larger.scss","../../../bower_components/font-awesome/scss/_fixed-width.scss","../../../bower_components/font-awesome/scss/_list.scss","../../../bower_components/font-awesome/scss/_variables.scss","../../../bower_components/font-awesome/scss/_bordered-pulled.scss","../../../bower_components/font-awesome/scss/_spinning.scss","../../../bower_components/font-awesome/scss/_rotated-flipped.scss","../../../bower_components/font-awesome/scss/_mixins.scss","../../../bower_components/font-awesome/scss/_stacked.scss","../../../bower_components/font-awesome/scss/_icons.scss","../../../bower_components/wyrm/sass/wyrm_core/_font_icon_defaults.sass","../../../bower_components/wyrm/sass/wyrm_core/_wy_variables.sass","../../../bower_components/wyrm/sass/wyrm_core/_alert.sass","../../../sass/_theme_variables.sass","../../../bower_components/neat/app/assets/stylesheets/grid/_media.scss","../../../bower_components/wyrm/sass/wyrm_core/_button.sass","../../../bower_components/wyrm/sass/wyrm_core/_dropdown.sass","../../../bower_components/wyrm/sass/wyrm_core/_form.sass","../../../bower_components/neat/app/assets/stylesheets/grid/_outer-container.scss","../../../bower_components/neat/app/assets/stylesheets/settings/_grid.scss","../../../bower_components/neat/app/assets/stylesheets/grid/_span-columns.scss","../../../bower_components/wyrm/sass/wyrm_core/_neat_extra.sass","../../../bower_components/wyrm/sass/wyrm_core/_generic.sass","../../../bower_components/wyrm/sass/wyrm_core/_table.sass","../../../bower_components/wyrm/sass/wyrm_core/_type.sass","../../../bower_components/wyrm/sass/wyrm_addons/pygments/_pygments.sass","../../../bower_components/wyrm/sass/wyrm_addons/pygments/_pygments_light.sass","../../../sass/_theme_breadcrumbs.sass","../../../sass/_theme_layout.sass","../../../bower_components/neat/app/assets/stylesheets/grid/_private.scss","../../../sass/_theme_badge.sass","../../../sass/_theme_rst.sass","../../../sass/_theme_mathjax.sass","../../../sass/_theme_font_local.sass"], +"names": [], +"file": "theme.css" +} diff --git a/content/docs/_static/doctools.js b/content/docs/_static/doctools.js new file mode 100644 index 0000000000..c7bfe760aa --- /dev/null +++ b/content/docs/_static/doctools.js @@ -0,0 +1,263 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + */ +jQuery.urldecode = function(x) { + return decodeURIComponent(x).replace(/\+/g, ' '); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s == 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node) { + if (node.nodeType == 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { + var span = document.createElement("span"); + span.className = className; + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this); + }); + } + } + return this.each(function() { + highlight(this); + }); +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated == 'undefined') + return string; + return (typeof translated == 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated == 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) == 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this == '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/content/docs/_static/down-pressed.png b/content/docs/_static/down-pressed.png new file mode 100644 index 0000000000..7c30d004b7 Binary files /dev/null and b/content/docs/_static/down-pressed.png differ diff --git a/content/docs/_static/down.png b/content/docs/_static/down.png new file mode 100644 index 0000000000..f48098a43b Binary files /dev/null and b/content/docs/_static/down.png differ diff --git a/content/docs/_static/file.png b/content/docs/_static/file.png new file mode 100644 index 0000000000..254c60bfbe Binary files /dev/null and b/content/docs/_static/file.png differ diff --git a/content/docs/_static/fonts/FontAwesome.otf b/content/docs/_static/fonts/FontAwesome.otf new file mode 100644 index 0000000000..8b0f54e47e Binary files /dev/null and b/content/docs/_static/fonts/FontAwesome.otf differ diff --git a/content/docs/_static/fonts/Inconsolata-Bold.ttf b/content/docs/_static/fonts/Inconsolata-Bold.ttf new file mode 100644 index 0000000000..360a232dd0 Binary files /dev/null and b/content/docs/_static/fonts/Inconsolata-Bold.ttf differ diff --git a/content/docs/_static/fonts/Inconsolata.ttf b/content/docs/_static/fonts/Inconsolata.ttf new file mode 100644 index 0000000000..4b8a36d249 Binary files /dev/null and b/content/docs/_static/fonts/Inconsolata.ttf differ diff --git a/content/docs/_static/fonts/Lato-Bold.ttf b/content/docs/_static/fonts/Lato-Bold.ttf new file mode 100644 index 0000000000..e8b9bf6a20 Binary files /dev/null and b/content/docs/_static/fonts/Lato-Bold.ttf differ diff --git a/content/docs/_static/fonts/Lato-Regular.ttf b/content/docs/_static/fonts/Lato-Regular.ttf new file mode 100644 index 0000000000..7608bc3e0f Binary files /dev/null and b/content/docs/_static/fonts/Lato-Regular.ttf differ diff --git a/content/docs/_static/fonts/RobotoSlab-Bold.ttf b/content/docs/_static/fonts/RobotoSlab-Bold.ttf new file mode 100644 index 0000000000..e6ed0de530 Binary files /dev/null and b/content/docs/_static/fonts/RobotoSlab-Bold.ttf differ diff --git a/content/docs/_static/fonts/RobotoSlab-Regular.ttf b/content/docs/_static/fonts/RobotoSlab-Regular.ttf new file mode 100644 index 0000000000..141d6c08c8 Binary files /dev/null and b/content/docs/_static/fonts/RobotoSlab-Regular.ttf differ diff --git a/content/docs/_static/fonts/fontawesome-webfont.eot b/content/docs/_static/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000000..7c79c6a6bc Binary files /dev/null and b/content/docs/_static/fonts/fontawesome-webfont.eot differ diff --git a/content/docs/_static/fonts/fontawesome-webfont.svg b/content/docs/_static/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000000..45fdf33830 --- /dev/null +++ b/content/docs/_static/fonts/fontawesome-webfont.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/_static/fonts/fontawesome-webfont.ttf b/content/docs/_static/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000000..e89738de5e Binary files /dev/null and b/content/docs/_static/fonts/fontawesome-webfont.ttf differ diff --git a/content/docs/_static/fonts/fontawesome-webfont.woff b/content/docs/_static/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000000..8c1748aab7 Binary files /dev/null and b/content/docs/_static/fonts/fontawesome-webfont.woff differ diff --git a/content/docs/_static/jquery-1.11.1.js b/content/docs/_static/jquery-1.11.1.js new file mode 100644 index 0000000000..d4b67f7e6c --- /dev/null +++ b/content/docs/_static/jquery-1.11.1.js @@ -0,0 +1,10308 @@ +/*! + * jQuery JavaScript Library v1.11.1 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-05-01T17:42Z + */ + +(function( global, factory ) { + + if ( typeof module === "object" && typeof module.exports === "object" ) { + // For CommonJS and CommonJS-like environments where a proper window is present, + // execute the factory and get jQuery + // For environments that do not inherently posses a window with a document + // (such as Node.js), expose a jQuery-making factory as module.exports + // This accentuates the need for the creation of a real window + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +// + +var deletedIds = []; + +var slice = deletedIds.slice; + +var concat = deletedIds.concat; + +var push = deletedIds.push; + +var indexOf = deletedIds.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var support = {}; + + + +var + version = "1.11.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android<4.1, IE<9 + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: deletedIds.sort, + splice: deletedIds.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + // parseFloat NaNs numeric-cast false positives (null|true|false|"") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( support.ownLast ) { + for ( key in obj ) { + return hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call(obj) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Support: Android<4.1, IE<9 + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( indexOf ) { + return indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + while ( j < len ) { + first[ i++ ] = second[ j++ ]; + } + + // Support: IE<9 + // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) + if ( len !== len ) { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: function() { + return +( new Date() ); + }, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v1.10.19 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-04-18 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + characterEncoding + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document (jQuery #6963) + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== strundefined && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, + doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent !== parent.top ) { + // IE11 does not have attachEvent, so all must suffer + if ( parent.addEventListener ) { + parent.addEventListener( "unload", function() { + setDocument(); + }, false ); + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", function() { + setDocument(); + }); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { + div.innerHTML = "
"; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [ m ] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( div.querySelectorAll("[msallowclip^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( div.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (oldCache = outerCache[ dir ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + outerCache[ dir ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context !== document && context; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is no seed and only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +}); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return typeof rootjQuery.ready !== "undefined" ? + rootjQuery.ready( selector ) : + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.extend({ + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +jQuery.fn.extend({ + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.unique( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); +var rnotwhite = (/\S+/g); + + + +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + + } else if ( !(--remaining) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); + + +// The deferred used on DOM ready +var readyList; + +jQuery.fn.ready = function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; +}; + +jQuery.extend({ + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + jQuery( document ).off( "ready" ); + } + } +}); + +/** + * Clean-up method for dom ready events + */ +function detach() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } +} + +/** + * The ready event handler and self cleanup method + */ +function completed() { + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } +} + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + + +var strundefined = typeof undefined; + + + +// Support: IE<9 +// Iteration over object's inherited properties before its own +var i; +for ( i in jQuery( support ) ) { + break; +} +support.ownLast = i !== "0"; + +// Note: most support tests are defined in their respective modules. +// false until the test is run +support.inlineBlockNeedsLayout = false; + +// Execute ASAP in case we need to set body.style.zoom +jQuery(function() { + // Minified: var a,b,c,d + var val, div, body, container; + + body = document.getElementsByTagName( "body" )[ 0 ]; + if ( !body || !body.style ) { + // Return for frameset docs that don't have a body + return; + } + + // Setup + div = document.createElement( "div" ); + container = document.createElement( "div" ); + container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; + body.appendChild( container ).appendChild( div ); + + if ( typeof div.style.zoom !== strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; + + support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; + if ( val ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); +}); + + + + +(function() { + var div = document.createElement( "div" ); + + // Execute the test only if not already executed in another module. + if (support.deleteExpando == null) { + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +})(); + + +/** + * Determines whether an object can have data + */ +jQuery.acceptData = function( elem ) { + var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ], + nodeType = +elem.nodeType || 1; + + // Do not set data on non-element DOM nodes because it will not be cleared (#8335). + return nodeType !== 1 && nodeType !== 9 ? + false : + + // Nodes accept data unless otherwise specified; rejection can be conditional + !noData || noData !== true && elem.getAttribute("classid") === noData; +}; + + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /([A-Z])/g; + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + +function internalData( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements (space-suffixed to avoid Object.prototype collisions) + // throw uncatchable exceptions if you attempt to set expando properties + noData: { + "applet ": true, + "embed ": true, + // ...but Flash objects (which have this classid) *can* handle expandos + "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var i, name, data, + elem = this[0], + attrs = elem && elem.attributes; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE11+ + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + + +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHidden = function( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); + }; + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; +}; +var rcheckableType = (/^(?:checkbox|radio)$/i); + + + +(function() { + // Minified: var a,b,c + var input = document.createElement( "input" ), + div = document.createElement( "div" ), + fragment = document.createDocumentFragment(); + + // Setup + div.innerHTML = "
a"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName( "tbody" ).length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = + document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>"; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + input.type = "checkbox"; + input.checked = true; + fragment.appendChild( input ); + support.appendChecked = input.checked; + + // Make sure textarea (and checkbox) defaultValue is properly cloned + // Support: IE6-IE11+ + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // #11217 - WebKit loses check when the name is after the checked attribute + fragment.appendChild( div ); + div.innerHTML = ""; + + // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 + // old WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + support.noCloneEvent = true; + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Execute the test only if not already executed in another module. + if (support.deleteExpando == null) { + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + } +})(); + + +(function() { + var i, eventName, + div = document.createElement( "div" ); + + // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event) + for ( i in { submit: true, change: true, focusin: true }) { + eventName = "on" + i; + + if ( !(support[ i + "Bubbles" ] = eventName in window) ) { + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + div.setAttribute( eventName, "t" ); + support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +})(); + + +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && jQuery.acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + // Support: IE < 9, Android < 4.0 + src.returnValue === false ? + returnTrue : + returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && e.stopImmediatePropagation ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + jQuery._removeData( doc, fix ); + } else { + jQuery._data( doc, fix, attaches ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + col: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!support.noCloneEvent || !support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + deletedIds.push( id ); + } + } + } + } + } +}); + +jQuery.fn.extend({ + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + remove: function( selector, keepData /* Internal Use Only */ ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map(function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var arg = arguments[ 0 ]; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + arg = this.parentNode; + + jQuery.cleanData( getAll( this ) ); + + if ( arg ) { + arg.replaceChild( elem, this ); + } + }); + + // Force removal if there was no new content (e.g., from empty arguments) + return arg && (arg.length || arg.nodeType) ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + + +var iframe, + elemdisplay = {}; + +/** + * Retrieve the actual display of a element + * @param {String} name nodeName of the element + * @param {Object} doc Document object + */ +// Called only from within defaultDisplay +function actualDisplay( name, doc ) { + var style, + elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + + // getDefaultComputedStyle might be reliably used only on attached element + display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? + + // Use of this method is a temporary fix (more like optmization) until something better comes along, + // since it was removed from specification and supported only in FF + style.display : jQuery.css( elem[ 0 ], "display" ); + + // We don't have any data stored on the element, + // so use "detach" method as fast way to get rid of the element + elem.detach(); + + return display; +} + +/** + * Try to determine the default display value of an element + * @param {String} nodeName + */ +function defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + + // Use the already-created iframe if possible + iframe = (iframe || jQuery( " + + +

+
+

Prerequisites

+

You will need to test with a mobile device running the platform you’re +developer for. In the case of Android, you might be able to use an +emulator. It is not possible to test push notifications from a web +browser.

+
+

iOS Prerequisites

+

To develop push notifications for an iOS app, you’ll need:

+
    +
  • A Mac to generate the necessary SSL certificate.
  • +
  • An iOS developer account. You’ll need this to register for an App ID +and get a provisioning profile. To get an account, visit the iOS Dev +Center.
  • +
  • An actual iOS device to test push notifications. It’s not yet +possible to develop push notifications with an emulator.
  • +
  • An iOS provisioning profile For iOS app testing, you need a +provisioning profile that’s associated with an Apple ID. You set up +the provisioning profile in the Apple developer portal, download the +profile, and import it into Xcode.
  • +
+

To set up a provisioning profile, you need to create an “iOS App +Development” certificate in the Apple developer portal. For example, in +the Apple APNs setup earlier in this tutorial, you created a certificate +in the Apple developer portal to be used for push notifications. +However, you won’t be able to create a provisioning portal with just +that certificate. You also need to create an “iOS App Development” +certificate (the configuration settings don’t matter), as shown in the +following image.

+../_images/ios-cert.png +

After you create an iOS App Development certificate, you can create a +provisioning profile that includes your App ID/certificate for push +notifications.

+
+
+

Android Prerequisites

+

It’s generally a best practice to develop Android apps by testing and +debugging with an Android device. It’s also possible to use an emulator.

+

Before testing and debugging with an Android device, you’ll need to set +up your device for development. Be sure to see the Android documentation +on using hardware +devices.

+

To test with an emulator, you will need to follow these steps:

+
    +
  1. Ensure that you have Google API 8 (or above) and Android 2.2 (or +above).
  2. +
  3. Using the Android SDK Manager, install Google Cloud Messaging for +Android Library.
  4. +
  5. Using the Android Virtual Device Manager, create an emulator whose +target is Google APIs.
  6. +
  7. Ensure that the emulator you’re using includes a Google account.
  8. +
+

Next:

+
    +
  • Launch the emulator.
  • +
  • In the emulator, click the Menu button, then go to Settings > +Accounts & Sync.
  • +
  • Add a Google account.
  • +
  • Once you’ve finished these steps, you should have an emulator that +can receive push notification messages.
  • +
+
+
+

PhoneGap Prerequisites

+

You’ll need to test with a device or emulator. It is not possible to +test push notifications with a browser alone.

+
+
+
+

Setup overview

+

The following steps get you set up so that your app can receive push +notifications. Keep in mind that these steps build on one another. In +other words, you’ll need values generated in step 1 in order to complete +step 2, and so on.

+

For a walkthrough of these steps using a push sample app, see Tutorial: +Push notifications sample app.

+
    +
  1. Register your app with push notification services. Your +notification messages will be forwarded to devices by Apple and/or +Google. So you’ll need to register with Apple APNs and/or Google’s +GCM. For more information, see Registering with a notification +service.
  2. +
  3. Create a notifier to send notification messages from the Usergrid +to notification services. The Usergrid will use your notifier to send +your messages to a notification service. For details, see Creating +notifiers. To create a notifier, you’ll need information generated by +registering with a push notification service. You’ll need a separate +notifier for each app/platform combination.
  4. +
  5. Register devices at run time. At run time, your code will +register to receive notifications. To do this, your code uses +information from the notification service and your notifier. For +more, see Managing users and devices.
  6. +
  7. Send and manage push notifications. You use Usergrid API +notification endpoints to target devices, users, or groups with your +messages. To learn more, see Creating and managing notifications.
  8. +
+
+
+

How it works

+

Click a tab below to view more information about how the pieces connect +once you’ve got it set up.

+
+

Apple APNs

+

The diagram below illustrates what things should look like once you’ve +gotten set up to send notifications that are received by your app.

+

A. At configuration time, you create an App +ID, then create a +notifier with a .p12 certificate you +generate on your Mac. The .p12 certificate correlates the notifier +(which you will use to send notification messages) with the App ID (so +that APNs will forward your notifications to devices).

+

B. A run time, your app’s code registers with Apple for +notifications by invoking the +registerForRemoteNotificationTypes method to receive a token it can +send to Usergrid.

+

C. At run time, your app’s code registers with the Usergrid for +notifications by sending the name +of the notifier you created. This ensure’s that there’s a device entity +in your Usergrid application. That way, you can address the device with +notification messages.

+../_images/pushmiddleios0.png +

Note: For information on troubleshooting push notifications on iOS +devices, see Troubleshooting Push +Notifications

+
+
+

Google GCM

+

The diagram below illustrates what things should look like once you’ve +gotten set up to send notifications that are received by your app.

+

A. At configuration time, you create a Google API +project), then create an Usergrid +notifier with an API key from the project. +The API key correlates the notifier (which you will use to send +notification messages from the Usergrid) with the API project (which +will forward your notifications to devices).

+

B. At run time, your app’s code registers with the +Usergrid) for notifications by +sending the name of the notifier you created. This ensure’s that there’s +a device entity in your Usergrid application. That way, you can address +the device with notification messages.

+

C. A run time, your app’s code registers with Google for +notifications) by sending the +number of your API project as a “sender ID”. The project is the actual +notification “sender” that will forward notifications to your app. In +other words, the app is telling Google that it wants to receive +notifications from that sender.

+../_images/pushmiddleandroid0.png +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/push-notifications/managing-users-and-devices.html b/content/docs/push-notifications/managing-users-and-devices.html new file mode 100644 index 0000000000..9622e70b6e --- /dev/null +++ b/content/docs/push-notifications/managing-users-and-devices.html @@ -0,0 +1,686 @@ + + + + + + + + + + + Managing users and devices — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Managing users and devices

+

Before your app can receive notifications on a user’s device, the app’s +code will need to register the device with both the Usergrid and the +appropriate push notification service (Apple APNs or Google GCM).

+

By registering with the Usergrid, your app adds the device on which it +is installed to your data store. The device is represented as a Device +entity. This makes it possible for you to target that device when +sending notifications. (For more on the Device entity, see the API +Docs.) Any devices, users, and +groups that have been registered in this way may be targeted with push +notifications.

+

By registering with the notification service, you make the device known +to the service. This way, the service can forward your notifications to +the device.

+

Note

+

+ + +For an overview of how to set up push notifications, including

troubleshooting tips, see Adding push notifications +support.

+

+

Registering devices

+

The following samples illustrate how to register a device with a +notification service and with the Usergrid. At a high level, your code +will send a registration request to the notification service, then use +information in the service’s response to send a separate request to the +Usergrid. The two requests correlate the notification service, Usergrid, +and your mobile app.

+

You can also create device entities separately by using the /devices +endpoint. For more information on using the /devices endpoint in the +Usergrid, see the API Docs.

+

Registering a device with a notification service is a standard coding +activity for implementing push notifications. This is not specific to +the Usergrid.

+
+

Registering for iOS

+

The following code illustrates how you can use the iOS SDK to register a +device with both the Usergrid server and with the APNs, the Apple push +notification service. This example assumes that your code has already +property initialized the SDK. For more information, see Installing the +Apigee SDK for iOS.

+
// Register with Apple to receive notifications.
+
+// Invoked when the application moves from an inactive to active state. Use this
+// method to register with Apple for notifications.
+- (void)applicationDidBecomeActive:(UIApplication *)application
+{
+    // Find out what notification types the user has enabled.
+    UIRemoteNotificationType enabledTypes =
+        [application enabledRemoteNotificationTypes];
+
+    // If the user has enabled alert or sound notifications, then
+    // register for those notification types from Apple.
+    if (enabledTypes & (UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeSound)) {
+
+        // Register for push notifications with Apple
+        NSLog(@"registering for remote notifications");
+        [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert |
+         UIRemoteNotificationTypeSound];
+    }
+}
+
+// Invoked as a callback from calling registerForRemoteNotificationTypes.
+// newDeviceToken is a token received from registering with Apple APNs.
+// Use this method to register with Apigee.
+- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)newDeviceToken
+{
+    // Register device token with the Usergrid (will create the Device entity if it doesn't exist)
+    // Sends the name of the notifier you created with Apigee, along with the token your code
+    // received from Apple.
+    ApigeeClientResponse *response = [dataClient setDevicePushToken: newDeviceToken
+                                                        forNotifier: notifier];
+
+    if ( ! [response completedSuccessfully]) {
+        [self alert: response.rawResponse title: @"Error"];
+    }
+}
+
+// Invoked as a callback from calling registerForRemoteNotificationTypes if registration
+// failed.
+- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
+{
+    [self alert: error.localizedDescription title: @"Error"];
+}
+
+
+

Initialize the Apigee client and check for notifications that might have +been sent while the app was off.

+
// Invoked as a callback after the application launches.
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+    // Connect and login
+    ApigeeClient *apigeeClient =
+        [[ApigeeClient alloc] initWithOrganizationId:orgName
+                                       applicationId:appName
+                                             baseURL:baseURL];
+    dataClient = [apigeeClient dataClient];
+    [dataClient setLogging:true]; //comment out to remove debug output from the console window
+
+    // Find out if there's a notification waiting to be handled after the
+    // app launches.
+    if (launchOptions != nil) {
+        NSDictionary* userInfo =
+            [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
+
+        // If there's notification data waiting, send it to be processed.
+        if (userInfo) {
+            [self handlePushNotification:userInfo
+                          forApplication:application];
+        }
+    }
+
+    // It's not necessary to explicitly login if the Guest role allows access.
+    // But this is how you can do it.
+//    [apigeeClient logInUser: userName password: password];
+
+    NSLog(@"done launching");
+    return YES;
+}
+
+
+
+
+

Registering for Android

+

The following code illustrates how to register a client device with GCM, +register the device with Apigee, and associate the device with the user. +Methods used in this code are defined in the Apigee Android SDK. For +more information on downloading and installing the SDK, see Installing +the Apigee SDK for Android.

+
import android.content.Context;
+import com.google.android.gcm.GCMRegistrar;
+import com.apigee.sdk.ApigeeClient;
+import com.apigee.sdk.data.client.entities.Device;
+
+/**
+ * Registers this device with GCM, Google's messaging
+ * service.
+ *
+ * @param context An Android context with information specific to this
+ * application's context on the device.
+ */
+static void registerPush(Context context) {
+
+    //Get an instance of the Apigee DataClient class from the ApigeeClient object
+    dataClient = getClient().getDataClient();
+
+    // Get the registration ID (GCM API key) for this application.
+    final String regId = GCMRegistrar.getRegistrationId(context);
+
+    // If this device isn't already registered with GCM, register it
+    // using the the application context and an ID for the Google account
+    // authorized to send messages to this application. This is the
+    // Google Client ID from Google API Console.
+    if ("".equals(regId)) {
+      GCMRegistrar.register(context, gcmSenderId);
+    } else {
+        if (GCMRegistrar.isRegisteredOnServer(context)) {
+            Log.i(TAG, "Already registered with GCM");
+        } else {
+
+        // Use an instance of the Client class (SDK for Android)
+        // to register this device with the Usergrid. Pass as arguments
+        // the device unique identifier, the unique name of the notifier you
+        // created in the Usergrid, the GCM API key, and a callback that will
+        // receive an instance of a Device class representing the registered
+        // device on the system.
+        dataClient.registerDeviceForPushAsync(dataClient.getUniqueDeviceID(), notifierName, regId, null,
+            new DeviceRegistrationCallback() {
+                @Override
+                public void onResponse(Device device) {
+                    AppServices.device = device;
+
+                    // Associate the logged in user with this device.
+                    if (dataClient.getLoggedInUser() != null) {
+                        dataClient.connectEntitiesAsync("users",
+                            dataClient.getLoggedInUser().getUuid().toString(),
+                            "devices", device.getUuid().toString(),
+                            new ApiResponseCallback() {
+                                @Override
+                                public void onResponse(ApiResponse apiResponse) {
+                                  Log.i(TAG, "connect response: " + apiResponse);
+                                }
+
+                                @Override
+                                public void onException(Exception e) {
+                                  displayMessage(context, "Connect Exception: " + e);
+                                  Log.i(TAG, "connect exception: " + e);
+                                }
+                        });
+                    }
+                }
+
+            });
+        }
+    }
+}
+
+/**
+ * Create an instance of the SDK ApigeeClient class, setting
+ * values from your Apigee registration.
+ */
+static synchronized ApigeeClient getClient() {
+    if (client == null) {
+        client = new ApigeeClient();
+        client.setApiUrl("https://api.usergrid.com");
+        client.setOrganizationId("your-org");
+        client.setApplicationId("your-app");
+    }
+    return client;
+}
+
+
+
+
+

Registering for HTML5/PhoneGap

+

The following code illustrates how you can use the JavaScript functions +included with the PhoneGap plugin to register a device with both the +Apigee server and with the APNs, the Apple push notification service.

+
// Declare a variable for calling push notification APIs.
+var pushNotification = window.plugins.pushNotification;
+// Collect configuration options to specify that this device accepts
+// an alert message, an application badge, and a sound.
+var appleOptions = {
+    alert:true, badge:true, sound:true
+};
+// Register the device with the Usergrid, passing options for configuration
+// along with a callback from which you can retrieve the device token
+// sent by Apigee.
+pushNotification.registerDevice(appleOptions, function(status) {
+    console.log(status);
+    // If a token was received, bundle options to pass when registering the device
+    // with the push notification service. The provider value must be "apigee" to
+    // support push notification through Apigee. orgName and appName should be
+    // values corresponding to those used in your Apigee account.
+    // notifier is the unique name you associated with the Apigee notifier you created.
+    // token is the device token this code received from Apigee after registering the
+    // device.
+    if(status.deviceToken) {
+        var options = {
+            "provider":"apigee",
+            "orgName":"YOUR APIGEE.COM USERNAME",
+            "appName":"sandbox",
+            "notifier":"YOUR NOTIFIER",
+            "token":status.deviceToken
+        };
+
+        // Use the device token and other options to register this device with the
+        // push notification provider.
+        pushNotification.registerWithPushProvider(options, function(status){
+            console.log(status);
+        });
+    }
+});
+
+
+

The functions used in this code are defined in the PhoneGap plugin. +JavaScript functions invoke underlying Objective-C or Java code +(depending on platform). You’ll find that code in these files, included +in the Apigee PhoneGap push notification plug-in.

+

Information about installing the plugin is available in its Readme file. +For more complete examples, see Tutorial: Push notifications sample +app.

+
+
+
+

Connecting devices to users

+

You can associate user entities with device entities in the Usergrid. +Doing so allows you to target your push notifications at users with +specific characteristics. The following describes how to connect a user +to a specific device in the Usergrid.

+

For more information on creating a device in your Usergrid data store, +see “Registering Devices” above.

+

For more information on creating a user in your Usergrid data store, see +User.

+

The following code examples all use the same basic endpoint pattern for +connecting devices with users:

+
POST /users/{userUUID or name}/devices/{deviceUUID}
+
+
+
+

Connecting with curl

+

The following call connects user “joex” with device +7a0a1cba-9a18-3bee-8ae3-4f511f12a386 (the device UUID). After this +connection, you can send a push notification to joex rather than the +device. Further, if joex has specific properties set–such as +{“favoritecolor”: “blue”}–you can send a push notification to all users +whose favorite color is blue (assuming they’re connected to devices in +the Usergrid).

+
curl -X POST "https://api.usergrid.com/my-org/sandbox/users/joex/devices/7a0a1cba-9a18-3bee-8ae3-4f511f12a386"
+
+
+
+
+

Connecting with iOS

+

The following sample code, taken from AppDelegate.m in the native iOS +push sample, uses the connectEntities method from the iOS SDK to connect +a device to a user.

+
ApigeeClientResponse *response = [dataClient setDevicePushToken: newDeviceToken forNotifier: notifier];
+
+// You could use this if you log in as an Usergrid user to associate the Device to your User
+if (response.transactionState == kUGClientResponseSuccess) {
+    response = [self connectEntities: @"users" connectorID: @"me" type: @"devices" connecteeID: deviceId];
+}
+
+
+
+
+

Connecting with Android

+

The following sample code, taken from +AppServices.java +in the native Android push sample, uses the connectEntitiesAsync method +from the Android SDK to connect a device to an authenticated user.

+
// connect Device to current User - if there is one
+if (dataClient.getLoggedInUser() != null) {
+  dataClient.connectEntitiesAsync("users", dataClient.getLoggedInUser().getUuid().toString(),
+                                   "devices", device.getUuid().toString(),
+                                   new ApiResponseCallback() {...
+
+
+
+
+

Connecting with HTML5/JavaScript

+

The following code illlustrates how to associate the currently logged in +user with their device.

+
// You'll need a client from the JavaScript SDK.
+var client = new Apigee.Client({
+    // Initialize client.
+});
+
+// Get information about the current user so you can use
+// it to connect them with their device.
+client.getLoggedInUser(function(err, data, user) {
+    if(err) {
+        // Could not get the logged in user.
+    } else {
+        if (client.isLoggedIn()) {
+            // Using a PushNotification function to get the device ID as
+            // it is known to the Apigee system.
+            pushNotification.getApigeeDeviceId(function(results) {
+                if (results.deviceId) {
+                    // Use the JavaScript SDK connect function to register
+                    // a connection between the current user and their device.
+                    user.connect('devices', results.deviceId, function (err, data) {
+                        if (err) {
+                            // Could not make the connection.
+                        } else {
+                            // Call succeeded, so pull the connections back down.
+                            user.getConnections('devices', function (err, data) {
+                            if (err) {
+                                // Couldn't get the connections.
+                            } else {
+                                // Connection exists.
+                            });
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+

You can also connect users with groups so that you can send push +notifications to groups of users (and their associated devices), see +Working with group data.

+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/push-notifications/overview.html b/content/docs/push-notifications/overview.html new file mode 100644 index 0000000000..e66752c48e --- /dev/null +++ b/content/docs/push-notifications/overview.html @@ -0,0 +1,391 @@ + + + + + + + + + + + Push notifications overview — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Push notifications overview

+
+ + + + +
../_images/iphonemessage.png +
+

Reach your users with push

+

With the new push notifications feature in the Usergrid, you can send +announcements to your app’s users.

+
    +
  • Reach your app’s users with messages they care about.
  • +
  • Keep your app footprint low while communicating in a high-value +way with your app’s users.
  • +
+

Read more

+
+ +

+
+

Get started

+
+

Get started with a tutorial

+

Build your first push-enabled app using an Apigee sample.

+
+
+

Find what you can do with it

+

A video and introduction.

+
+
+

See the prerequisites

+

Depending on your supported app platforms, you’ll need just a few +things.

+
+
+
+

Build push support

+
+

Setting up push notifications support

+

Connect Apple or Google with Usergrid and your app.

+
+
+

Register your app

+

Register with Apple or Google.

+
+
+

Create a notifier

+

Your application uses this to send messages.

+
+
+

Register client devices

+

Your app code registers to receive notifications.

+
+
+

Send and manage notifications

+

You can do this from app code or the admin portal.

+
+
+
+

Learn more

+
+

Troubleshoot your push support

+

Things don’t work as you expect?

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/push-notifications/registering.html b/content/docs/push-notifications/registering.html new file mode 100644 index 0000000000..d43aa95273 --- /dev/null +++ b/content/docs/push-notifications/registering.html @@ -0,0 +1,482 @@ + + + + + + + + + + + Registering with a notification service — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Registering with a notification service

+

To send push notifications, you will need to first register your app +with the push notification service (Apple APNs or Google GCM) that +corresponds to your app’s platform. Once you’ve registered, the service +will provide you with a certificate or key that you will need when you +create an Usergrid notifier. (See Creating +notifiers for more information.)

+

Push notification services are gateways controlled by platform services +(such as Apple and Google). These gateways ensure that push +notifications are delivered securely and originate from trusted apps.

+

To send push notifications to your app on iOS devices, you’ll register +the the Apple Push Notification service (APNs). For app on Android, +you’ll register with Google Cloud Messaging for Android (GCM).

+

Note

+

+ + +For an overview of how to set up push notifications, see `Setting up

push notification support <adding-push-support.html>`__.

+

+

Registering with Apple APNs

+

Before you can send push notifications to your app on iOS devices, +you’ll need to get set up so that Apple knows you’ll be sending +notifications. To do that, you’ll need to do the following:

+
    +
  • Generate an SSL signing certificate you can use to generate a .p12 +certificate.
  • +
  • Create an Apple App ID through which you can associate push +notifications support with your app.
  • +
  • Generate a .p12 certificate you can use to create an Usergrid +notifier. The certificate will be sent to APNs with push notification +requests.
  • +
+

For more information see “How the pieces connect” in Setting up push +notification support.

+

Note

+

+ + +You'll need a Mac to generate a .p12 certificate and work with APNs.

+

Generating an SSL signing certificate

+

First, you’ll create an SSL signing certificate that you can use to +generate a .p12 certificate. To generate an SSL signing certificate, do +the following:

+
    +
  1. On your development machine, launch the Keychain Access application.
  2. +
  3. From the Keychain Access menu, select Certificate Assistant > +Request a Certificate From a Certificate Authority.
  4. +
  5. Enter a contact email address and a name you will use to sign your +apps.
  6. +
  7. Select Saved to disk, then click Continue.
  8. +
  9. Select Desktop from the Where drop-down, then click Save to +download the .certSigningRequest file.
  10. +
  11. Click Done once the download has completed.
  12. +
+
+
+

Creating an App ID

+

Next, you must create an App ID for your app. The App ID uniquely +identifies your app and provides a way for you to configure the app for +push notification support. (For more on App IDs, see Creating and +Configuring App +IDs.)

+

Note

+

+ + +An iOS developer account is required to complete these steps. To

register for an iOS developer account, visit the Apple Developer +site.

+

    +
  1. Log in to Apple’s iOS developer +portal.
  2. +
  3. In the iOS Apps section, click Identifiers, then select App +IDs.
  4. +
  5. Click the + icon to create a new App ID, and enter the following:
  6. +
+
    +
  • App ID Description - Name: A unique name that identifies your +app.
  • +
  • App BaaS: Select Push Notifications.
  • +
  • App ID Suffix: Select Explicit App ID, and enter your desired App +ID in reverse-domain format. For example, com.apigee.pushapp.
  • +
+
    +
  1. Click Submit to create the App ID, then click Done. You will +be returned to the App IDs page.
  2. +
+
+
+

Generating a .p12 certificate

+

Finally, you will generate the .p12 certificate using the App ID and +signing certificate you created in the previous steps. The .p12 +certificate will be sent by Apigee to Apple APNs with all push +notification requests. A unique .p12 certificate is required for each +app. In addition, you should create separate .p12 certificates for +development and production versions of your app.

+
    +
  1. On the App IDs page, click your new App ID, then click Edit.
  2. +
  3. In the Push Notifications section, under Development SSL Certificate, +click Create Certificate.
  4. +
+../_images/pushsslcertificate.png +
    +
  1. Click Choose File, select the .certSigningRequest file you saved +to your Desktop in the previous section, then click Generate.
  2. +
  3. Click Done. You will be returned to the App ID settings window.
  4. +
  5. In the Push Notifications section, click Download to save the +certificate (aps_development.cer file) to your Desktop.
  6. +
  7. Double-click the .cer file to install it in your keychain. The newly +installed certificate will appear in your Keychain Access +application under My Certificates with a name similar to “Apple +Development iOS Push Services: ”.
  8. +
  9. Control-click the certificate and select Export.
  10. +
  11. Save the certificate to your Desktop as a ‘Personal Information +Exchange (.p12)’ file. (You’ll need this file when you create a +notifier. For more information, see Creating +notifiers.
  12. +
  13. In the password dialog, leave the password field blank, then click +OK.
  14. +
  15. In the next dialog, enter your system password, then click +Allow.
  16. +
+
+
+
+

Registering with Google GCM

+

To create a notifier for sending notifications, you’ll need a Google API +project and register your app as part of that project. The project’s +identifier (project number) will become the sender ID your client code +will send when registering. Registering your app will give you an API +key you’ll use to create a notifier. (For more information see “How the +pieces connect” in Adding push notifications +support.)

+

The following is an abbreviated version of the steps described in the +Google documentation on getting started with Google Cloud +Messaging.

+

To generate a project number and API key, do the following:

+
    +
  1. Go to the Google API developer web +site and log in with your +Google ID.
  2. +
  3. Click Create Project, enter a project name and ID, then follow +the steps required to verify.
  4. +
  5. In the left nav, click Overview to view the project number. Note +this number for later use in client code.
  6. +
+../_images/googleproj0.png +
    +
  1. Click APIs in the left nav area, then click the button to enable +Google Cloud Messaging for Android.
  2. +
+../_images/gcmsetting.png +
    +
  1. In the left nav, under APIs and auth, click Credentials.
  2. +
  3. Under Public API access, click Create New Key.
  4. +
  5. In the Create a new key dialog, click Server key. Take care +not to choose “Android key,” though you might be tempted to. +Remember that your push notification requests will be received by +Google from Apigee’s server (via the notifier your code sends to +Apigee), rather than directly from the device your app is installed +on.
  6. +
  7. On the Create a server key... dialog, enter the IP address of +the server that will be sending the notification request to Google.
  8. +
  9. Click Create.
  10. +
  11. On the Credentials page, under Key for server applications, copy +the API key value for use when creating a notifier to request +push notifications from GCM. (For more information, see Creating +notifiers.)
  12. +
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/push-notifications/tbd.html b/content/docs/push-notifications/tbd.html new file mode 100644 index 0000000000..27adef1dd4 --- /dev/null +++ b/content/docs/push-notifications/tbd.html @@ -0,0 +1,294 @@ + + + + + + + + + + + COMING IN USERGRID 2 — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

COMING IN USERGRID 2

+
+ + +
+
+
+ + +
+ +
+

+ © Copyright 2013-2015, Apache Usergrid. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/push-notifications/troubleshooting.html b/content/docs/push-notifications/troubleshooting.html new file mode 100644 index 0000000000..9677e3c4b7 --- /dev/null +++ b/content/docs/push-notifications/troubleshooting.html @@ -0,0 +1,464 @@ + + + + + + + + + + + Troubleshooting — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Troubleshooting

+
+

Working with Android

+
+

App fails to install on the emulator

+
    +
  • When using the emulator, be sure to note the setup steps in Push +notifications prerequisites.
  • +
  • Sometimes installation fails while the emulator is still being +launched. Wait until the emulator is up and running (so that you can +unlock and interact with the UI), then run the project again.
  • +
  • Make sure that the order of your Java Build Path matches the order +shown in Tutorial: Push notifications sample app.
  • +
+
+
+

Push errors

+

If pressing the button to send yourself a push throws an exception or +doesn’t respond:

+
    +
  • Make sure the emulator’s target matches the Google API version used +in the project.
  • +
  • In the IDE log, wait until you see that the device has been +registered before sending yourself a push. Sometimes waiting for the +code to run and trying another click gets the push message to you.
  • +
  • If you successfully send yourself a push message once but fail to +again, try one of the following:
  • +
+

Go to the apps list on the device and launch the app from there.

+

OR

+

Uninstall the app from the device, delete the device in the admin +portal, and run the project again.

+
+
+

MismatchSenderId error message from the server when it tries to send a message to your app.

+

The sender ID is a number you send to GCM from app code when registering +with GCM for notifications. The error might be occurring because the +sender ID with which your app is registering at GCM for notifications +does not correlate to the API project whose API key was used to create +your notifier. First, confirm the following:

+
    +
  • The sender ID in your app code (used when registering with GCM) is +the same as your Goole API project number.
  • +
  • The API key used to create your notifier is the same as the API key +in your Google API project.
  • +
  • The notifier name used in your app code is the same as for the +notifier you created in the Usergrid.
  • +
+

It can be possible to make a fix (such as by correcting the sender ID in +your app code) and still see this error. If you’re still seeing the +error, consider create a new API project and notifier, then use their +new values in your code:

+
    +
  1. Recreate (or create anew) the Google API project. This will generate +a new API key and project number. See Registering with a notification +service.
  2. +
  3. Create a new notifier for GCM using the API key you generated with +the new API project. See Creating notifiers.
  4. +
  5. Use the new notifier name in your code, along with a new sender ID +that is that same value as the Google API project number.
  6. +
+
+
+

INVALID_SENDER error message

+

The sender ID is a number you send to GCM from app code when registering +with GCM for notifications. The “sender” in this case is the Google API +project you created to send notification messages. Confirm that the +sender ID you’re using in code is the same value as the API project +number generated when you created your Google API project. See +Registering with a notification service.

+
+
+
+

Working with PhoneGap Android

+
+

App fails to install on the emulator

+
    +
  • When using the emulator, be sure to note the setup steps in +Tutorial: Push notifications sample app.
  • +
  • Sometimes installation fails while the emulator is still being +launched. Wait until the emulator is up and running (so that you can +unlock and interact with the UI), then run the project again.
  • +
  • Make sure that the order of your Java Build Path matches the order +shown in Tutorial: Push notifications sample app.
  • +
+
+
+

Push errors

+

If pressing the button to send yourself a push throws an exception or +doesn’t respond:

+
    +
  • Make sure the emulator’s target matches the Google API version used +in the project.
  • +
  • In the IDE log, wait until you see that the device has been +registered before sending yourself a push. Sometimes waiting for the +code to run and trying another click gets the push message to you.
  • +
  • If you successfully send yourself a push message once but fail to +again, try one of the following:
  • +
+

Go to the apps list on the device and launch the app from there.

+

OR

+

Uninstall the app from the device, delete the device using the admin +portal, then run the project again.

+
+
+

MismatchSenderId error message from the server when it tries to send a message to your app.

+

The sender ID is a number you send to GCM from app code when registering +with GCM for notifications. The error might be occurring because the +sender ID with which your app is registering at GCM for notifications +does not correlate to the API project whose API key was used to create +your notifier. First, confirm the following:

+
    +
  • The sender ID in your app code (used when registering with GCM) is +the same as your Google API project number.
  • +
  • The API key used to create your notifier is the same as the API key +in your Google API project.
  • +
  • The notifier name used in your app code is the same as for the +notifier you created in the Usergrid.
  • +
+

It can be possible to make a fix (such as by correcting the sender ID in +your app code) and still see this error. If you’re still seeing the +error, consider create a new API project and notifier, then use their +new values in your code:

+
    +
  1. Recreate (or create anew) the Google API project. This will generate +a new API key and project number. See Registering with a +notification service.
  2. +
  3. Create a new notifier for GCM using the API key you generated with +the new API project. See Creating +notifiers.
  4. +
  5. Use the new notifier name in your code, along with a new sender ID +that is that same value as the Google API project number.
  6. +
+
+
+

INVALID_SENDER error message

+

The sender ID is a number you send to GCM from app code when registering +with GCM for notifications. The “sender” in this case is the Google API +project you created to send notification messages. Confirm that the +sender ID you’re using in code is the same value as the API project +number generated when you created your Google API project. See +Registering with a notification service.

+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/push-notifications/tutorial.html b/content/docs/push-notifications/tutorial.html new file mode 100644 index 0000000000..28cfcb9de4 --- /dev/null +++ b/content/docs/push-notifications/tutorial.html @@ -0,0 +1,664 @@ + + + + + + + + + + + Tutorial: Push notifications sample app — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Tutorial: Push notifications sample app

+

In this tutorial, you’ll use a sample app (iOS, Android, or PhoneGap) to +send yourself a push notification with the Usergrid push notification +API. You’ll register with a push notification services (Apple APNs or +Google GCM) to create the required security certificate or key, create +the required Usergrid notifier to send a message, then modify, compile +and run the sample app to see push notifications in action.

+

Note

+

+ + +For an overview of how to set up push notifications, including

troubleshooting tips, see Adding push notifications +support.

+

+

Before you begin

+

Before you can add support for push notifications, be sure that you’re +set up for the requirements described in Adding push notifications +support.

+
+
+

Step 1: Download a sample app

+

Sample push notification apps are included in the /samples directory of +the following platform SDKs and plugins:

+ +

To begin this tutorial, download the sample app for the platform of your +choice.

+

A note to PhoneGap developers: PhoneGap requires a plugin to enable +push notifications. The plugin is included in the sample apps in the +JavaScript SDK. For new PhoneGap applications, download the PhoneGap +push plugin.

+
+
+

Step 2: Register with a notification service and generate a certificate/key

+

To send push notifications you must register your app with the push +notification service that corresponds to your app’s platform. Once +registered, the service will provide you with a certificate or key that +you will provide when creating an Usergrid notifier.

+

For a full walkthrough of how to register an app with a notification +service and generate the necessary certificate/key, see Registering +with a notification service.

+
+
+

Step 3: Create a notifier

+

Notifiers are entities that carry your push notifications to a +notification service. Once a notification service has verified that your +notifier contains valid credentials, it will deliver your push +notification to the devices of your app’s users.

+

For information on how to use the admin portal to create a notifier, see +Creating notifiers.

+
+
+

Step 4: Configure and run the sample app

+

In this step, you’ll open your sample app of choice in your IDE and +configure it. The Android sample app can be run with an emulator, +included in the Android Developer Tools. The iOS sample app must be run +on an actual iOS device.

+

The following sections provide platform-specific guidance for setting up +and running the samples. However, this content assumes that you +understand your development environment well enough to configure and +work with projects.

+
+

iOS Dev Setup

+

To configure and run the Native iOS push notification sample app, do the +following:

+
    +
  1. Open the iOS sample app with XCode by opening its .xcodeproj file.
  2. +
  3. Make the following changes to /Push Test/AppDelegate.m:
  4. +
+
    +
  • orgName: Your Apigee organization.
  • +
  • appName: The app in your organization where you created the +notifier. (For the sample, make sure it’s “sandbox”.)
  • +
  • notifier: Name of the notifier you created. (For the sample, make +sure it’s “appledev”.).
  • +
+
    +
  1. Plug your iOS device into your development machine.
  2. +
  3. In Xcode, select Window > Organizer to open the Xcode Organizer.
  4. +
  5. Under Devices, select the device you plugged in, then click +Add to Member Center. You may be prompted to log in with the +Apple ID associated with your Apple Developer account.
  6. +
  7. If prompted, select a Development Team to use for provisioning. This +will be a team you’ve registered at the Apple developer portal.
  8. +
  9. Log in to the Apple Developer +portal and create a provisioning +profile that includes the App ID you chose when you registered the +sample app with Apple APNs. For more information on how to create a +provisioning profile, see “About provisioning profiles” below.
  10. +
  11. Download the profile and add it into Xcode Organizer, in the +Provisioning Profiles group under your plugged-in device.
  12. +
  13. Close the Organizer.
  14. +
  15. In Xcode, select the Project Navigator, then select the project root +folder.
  16. +
  17. In the General tab, in the Bundle Identifer box, enter the +App ID associated with your provisioning profile.
  18. +
  19. In the Build Settings tab, under Deployment, for the iOS +Deployment Target select the iOS version on your connected device. +The version is displayed in the Xcode Organizer.
  20. +
  21. In the Build Settings tab, under Code Signing, under Code +Signing Identity > Debug, select the Apple signing certificate +corresponding to your developer identity.
  22. +
+../_images/iospushsettings.png +
    +
  1. Click Run to launch the sample on your iOS device.
  2. +
  3. When the “codesign wants to sign using key in your keychain.” dialog +is displayed, click Allow.
  4. +
  5. The project is now built, and the app is installed on your device. +The first time you run the push sample app, your device will ask +permission to allow push notifications. Tap OK.
  6. +
+../_images/iospushauth.png +
    +
  1. In the app, tap the push to this device button to send yourself +a push notification. If you have configured your notification to go +to multiple devices, tap the push to all devices button to send +the push notification to all devices.
  2. +
+../_images/iospushfinal.png +
+
+

PhoneGap iOS Dev Setup

+

To configure and run the PhoneGap iOS push notification sample app, do +the following:

+
    +
  1. Open the iOS PhoneGap sample app with Xcode by opening its .xcodeproj +file.
  2. +
  3. Make the following changes in /www/js/index.js:
  4. +
+
    +
  • orgName: Your Apigee organization.
  • +
  • appName: The app in your organization where you created the +notifier. (For the sample, make sure it’s “sandbox”.)
  • +
  • notifier: Name of the notifier you created.
  • +
+
    +
  1. Plug your iOS device into your development machine.
  2. +
  3. In Xcode, select Window > Organizer to open the Xcode Organizer.
  4. +
  5. Under Devices, select the device you plugged in, then click +Add to Member Center. You may be prompted to log in with the +Apple ID associated with your Apple Developer account.
  6. +
  7. If prompted, select a Development Team to use for provisioning. This +will be a team you’ve registered at the Apple developer portal.
  8. +
  9. Log in to the Apple Developer +portal and create a provisioning +profile that includes the App ID you chose when you registered the +sample app with Apple APNs. For more information on how to create a +provisioning profile, see “About provisioning profiles” below.
  10. +
  11. Download the profile and add it into Xcode Organizer, in the +Provisioning Profiles group under your plugged-in device.
  12. +
  13. Close the Organizer.
  14. +
  15. In Xcode, select the Project Navigator, then select the project root +folder.
  16. +
  17. In the General tab, in the Bundle Identifer box, enter the +App ID associated with your provisioning profile.
  18. +
  19. In the Build Settings tab, under Deployment, for the iOS +Deployment Target select the iOS version on your connected device. +The version is displayed in the Xcode Organizer.
  20. +
  21. In the Build Settings tab, under Code Signing, under Code +Signing Identity > Debug, select the Apple signing certificate +corresponding to your developer identity.
  22. +
+../_images/iospgsettings.png +
    +
  1. At the top of the IDE, ensure that the name for your plugged in +device is displayed next to the target name, then click the Run +button to launch the sample on your iOS device.
  2. +
  3. If the “codesign wants to sign using key in your keychain” dialog is +displayed, click Allow.
  4. +
  5. The project is now built, and the app is installed on your device. +The first time you run the push sample app, your device will ask +permission to allow push notifications. Tap OK.
  6. +
  7. In the app, tap the Send a push with Phonegap! button to send +yourself a push notification.
  8. +
+../_images/iospgapp.png +
+
+

About iOS provisioning profiles

+

For iOS app testing, you need a provisioning profile that’s associated +with an Apple ID. You set up the provisioning profile in the Apple +developer portal, download the profile, and import it into Xcode.

+

To set up a provisioning profile, you need to create an “iOS App +Development” certificate in the Apple developer portal. For example, in +the Apple APNs setup earlier in this tutorial, you created a certificate +in the Apple developer portal to be used for push notifications. +However, you won’t be able to create a provisioning portal with just +that certificate. You also need to create an “iOS App Development” +certificate (the configuration settings don’t matter), as shown in the +following image.

+../_images/iospgcert.png +

After you create an iOS App Development certificate, you can create a +provisioning profile that includes your App ID/certificate for push +notifications.

+
+
+

Android Dev Setup

+

To configure and run the native Android push notification sample app, do +the following:

+
    +
  1. Make sure you have the latest Android SDK installed in your IDE, and +that Android APIs have been installed via the Android SDK Manager.
  2. +
  3. Import the native Android sample app project into your IDE
  4. +
  5. Modify the following in /src/com.ganyo.pushtest/Settings.java:
  6. +
+
    +
  • GCM_SENDER_ID: Your Google Cloud Messaging (GCM) project +number, as described in the Tutorial: Push notifications sample app.
  • +
  • NOTIFIER: Name of your notifier. (For the sample, make sure it’s +the name of the notifier you created.)
  • +
  • ORG: Your Apigee organization.
  • +
  • APP: The app in your organization where you created the notifier. +(For the sample, make sure it’s “sandbox”.)
  • +
  • USER and PASSWORD: Optional. If you created your notifier in +an app other than “sandbox” (which doesn’t require authentication), +enter the username and password of one of your Usergrid admin users.
  • +
+
    +
  1. In AndroidManifest.xml, be sure the proper Android permissions are +included, such as READ_PHONE_STATE and VIBRATE.
  2. +
  3. In your project properties, go to Java Build Path > Libraries and +add all the JAR files from the project’s /libs directory.
  4. +
  5. In the Order and Export tab, move the JARs to the top of the list +and select all the check boxes. Make sure the order and selections +match the following image:
  6. +
+../_images/assettings.png +
    +
  1. If you’re using an emulator, configure the emulator to use the Google +APIs Level 16 target.
  2. +
+../_images/asemu.png +
    +
  1. Run the project as an Android Application. The IDE should compile the +project and install the app on your device.
  2. +
  3. Press the button on the app to send yourself a push notification.
  4. +
+../_images/asapp.png +
+
+

PhoneGap Android Dev Setup

+

To configure and run the PhoneGap Android push notification sample app, +do the following:

+
    +
  1. Make sure you have the latest Android SDK installed in your IDE, and +that Android APIs have been installed via the Android SDK Manager.
  2. +
  3. Import the PhoneGap Android sample app project into your IDE.
  4. +
  5. Modify the following in /assets/www/js/index.js:
  6. +
+
    +
  • orgName: Your apigee organization.
  • +
  • appName: The app in your organization where you created the +notifier. (For the sample, make sure it’s “sandbox”.)
  • +
  • notifier: Name of your notifier.
  • +
  • senderID: Your API project number (the project must support +Google Cloud Messaging for Android (GCM)), as described in the +Registering with a notification service.
  • +
+
    +
  1. In AndroidManifest.xml, be sure the proper Android permissions +are included. This includes READ_PHONE_STATE and VIBRATE.
  2. +
  3. In your project properties, go to Java Build Path > Libraries and +add all the JAR files from the project’s /libs directory.
  4. +
  5. In the Order and Export tab, move the JARs to the top of the list +and select all the check boxes. Make sure the order and selections +match the following image:
  6. +
+../_images/pgasettings.png +
    +
  1. If you’re using an emulator, configure the emulator to use the Google +APIs Level 16 target or above. Also, be sure to see the Android +requirements in Adding push notifications +support for steps on setting up the +emulator to support push notifications.
  2. +
+../_images/pgaspath.png +
    +
  1. Run the project as an Android Application. The IDE should compile the +project and install the app on your device.
  2. +
  3. Press the button on the app to send yourself a push notification.
  4. +
+../_images/pgaapp.png +

Note

+

+ + +For troubleshooting tips, see [Adding push notifications

support](adding-push-supprt.html.

+

+
+

More about PhoneGap

+

The PhoneGap iOS push notification sample was +created using standard web technologies such as HTML5, JavaScript, and +CSS. You build the app with those technologies, and PhoneGap provides +project templates for iOS, Android, and other platforms. For example, +atop platform-specific PhoneGap code, core app code between the iOS and +Android samples is essentially the same.

+

When using PhoneGap to develop push notification apps, you use a +PhoneGap plugin designed to support push notifications. That plugin is +included in the Apigee samples. For more about the plugin, see the +plugin’s GitHub +project.

+
+
+
+

Step 5: Review the data entities created by the sample app

+
    +
  1. Log in to the admin portal, and select Data in the left navigation +pane.
  2. +
  3. Select any of the following collections to view the entities that +were created in them by the push notification sample app:
  4. +
+
    +
  • /devices - To see the device that was added.
  • +
  • /notifications - To see the notification that was sent.
  • +
  • /receipts - To see the receipt generated from the successful +push.
  • +
+
+
+

Step 6: Send additional push notifications using other Usergrid tools

+

Send a push notification from the Usergrid Notifications console On the +Send Notification screen. Select your notifier, select All Devices, +enter a message, select Now, and click to send it.

+../_images/sendnotification.png +
+

Send a push notification directly via the push notifications API

+

Use the following curl command in a terminal window, replacing your-org, +your-app and notifier-name.

+
curl -X POST "https://api.usergrid.com/your-org/your-app/devices/*/notifications" -d '{"payloads":{"notifier-name":"I just sent another notification! Yea, me!"}}'
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/push-notifications/users-devices.html b/content/docs/push-notifications/users-devices.html new file mode 100644 index 0000000000..1faee133f3 --- /dev/null +++ b/content/docs/push-notifications/users-devices.html @@ -0,0 +1,551 @@ + + + + + + + + + + + Users & Devices — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Users & Devices

+

Users and Devices are the primary ways to identify access to the system. +Devices are great to track anonymous access, while Users allow you to +model signing up, signing in, etc.

+
+

Users

+
+
+

Properties

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
uuidUUIDUser’s unique entity ID
typestringType of entity, in this case “user”
createdlongUNIX timestamp of entity creation
modifiedlongUNIX timestamp of entity modification
usernamestringValid and unique string username (mandatory)
passwordstringUser password
emailstringValid and unique email address
namestringUser display name
activatedbooleanWhether the user account is activated
disabledbooleanWhether the user account is administratively disabled
firstnamestringUser first name
middlenamestringUser middle name
lastnamestringUser last name
picturestringUser picture
+
+
+

Sets

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
SetTypeDescription
connectionsstringSet of connection types (e.g., likes)
rolenamesstringSet of roles assigned to a user
permissionsstringSet of user permissions
credentialsstringSet of user credentials
+
+
+

Relationshops

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CollectionTypeDescription
groupsgroupCollection of groups to which a user belongs
devicesdeviceCollection of devices in the service
activitiesactivityCollection of activities a user has performed
feedactivityInbox of activity notifications a user has received
rolesroleSet of roles assigned to a user
+
+
+

Facebook Sign-in

+

You can authenticate your Apache Usergrid requests by logging into +Facebook. To access Apache Usergrid resources, you need to provide an +access token with each request (unless you use the sandbox app). You can +get an access token by connecting to an appropriate web service endpoint +and providing the correct client credentials — this is further described +in Authenticating users and application +clients. However, you +can also obtain an access token by logging into Facebook.

+

To enable authentication to Apache Usergrid through Facebook, do the +following in your app:

+
    +
  1. Make a login call to the Facebook API (do this using the Facebook +SDK or +API). If +the login succeeds, a Facebook access token is returned.

    +
  2. +
  3. Send the Facebook access token to Apache Usergrid. If the Facebook +access token is valid and the user does not already exist in App +Services, Apache Usergrid provisions a new Apache Usergrid user. It +also returns an Apache Usergrid access token, which you can use for +subsequent Apache Usergrid API calls. Behind the scenes, Apache +Usergrid uses the Facebook access token to retrieve the user’s +profile information from Facebook.

    +

    If the Facebook access token is invalid, Facebook returns an OAuth +authentication error, and the login does not succeed.

    +
  4. +
+

The request to authenticate to Apache Usergrid using a Facebook access +token is:

+
GET https://api.usergrid.com/{my_org}/{my_app}/auth/facebook?fb_access_token={fb_access_token}
+
+
+

where:

+
    +
  • {my_org} is the organization UUID or organization name.
  • +
  • {my_app} is the application UUID or application name.
  • +
  • {fb_access_token} is the Facebook access token.
  • +
+
+
+

Devices

+
+
+

Properties

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
uuidUUIDEntity unique ID
typestringEntity type (e.g., device)
createdlongUNIX timestamp of entity creation
modifiedlongUNIX timestamp of entity modification
namestringDevice name (mandatory)
+
+
+

Relationships

+

Devices have the following associated collection.

+ +++++ + + + + + + + + + + + + +
CollectionTypeDescription
usersuserCollection of users to which a device belongs
+
+
+ + +
+
+
+ + +
+ +
+

+ © Copyright 2013-2015, Apache Usergrid. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/reference/contribute-code.html b/content/docs/reference/contribute-code.html new file mode 100644 index 0000000000..e6de28f275 --- /dev/null +++ b/content/docs/reference/contribute-code.html @@ -0,0 +1,359 @@ + + + + + + + + + + + How to Contribute Code & Docs — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

How to Contribute Code & Docs

+
+

Contribute via GitHub

+

The Usergrid project uses GitHub as our code review system. If you want +to contribute to Usergrid, then you should fork the apache/usergrid repo +and submit PRs back to the project. Here are step-by-step guides for +both both external contributors and committers:

+ +
+
+

Building Usergrid

+

Usergrid is made up of multiple components that are built separately:

+
    +
  • Stack: The Usergrid Stack is a Java web application, built using +Maven.
      +
    • Build instructions are in the +README.
    • +
    +
  • +
  • Portal: The Usergrid Portal is an Angular.js application and +builds with Grunt.
      +
    • Build instructions are in the +README.
    • +
    +
  • +
  • SDKs: See the README files in the /sdks sub-directories for SDK +build instructions.
  • +
+
+
+

Building the Website and Documentation

+

Usergrid documentation source is located in the /docs directory of +our Git repo, written in +Markdown format and +managed by the Sphinx documentation +system. For more information:

+ +

The Usergrid website source is managed in the /website directory. We +use the Nanoc static-site generator to generate +website content from source. For more information:

+ +
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/reference/presos-and-videos.html b/content/docs/reference/presos-and-videos.html new file mode 100644 index 0000000000..db70fa8e73 --- /dev/null +++ b/content/docs/reference/presos-and-videos.html @@ -0,0 +1,349 @@ + + + + + + + + + + + Presentations & Videos — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Presentations & Videos

+
+

Building Mobile Apps with Apache Usergrid

+
    +
  • Screen-cast of a talk given by Dave Johnson at the All Things Open +2014, Raleigh, NC.
  • +
+
+
+

How to Contribute to Apache Usergrid

+ +
+
+

Apache Usergrid Internals

+
    +
  • Sungju Jin
  • +
+
+
+

Open Source Mobile Backend on Cassandra

+
    +
  • Ed Anuff
  • +
+
+
+

Usergrid Overview

+
    +
  • Ed Anuff
  • +
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/rest-endpoints/api-docs.html b/content/docs/rest-endpoints/api-docs.html new file mode 100644 index 0000000000..2872baae0e --- /dev/null +++ b/content/docs/rest-endpoints/api-docs.html @@ -0,0 +1,4216 @@ + + + + + + + + + + + Methods — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +

Usergrid API Reference

+

Methods are organized by tag. Follow the methods are the Model +Definitions.

+

Table of Contents

+

+
+

Methods

+
+

Access-Tokens

+

POST /management/token

+

Login with Admin-User or Organization credentials.

+

Parameters

+

    +
  • login-credentials (LoginCredentials) +Login credentials either username/password or id/secret. (Specified +in body).
  • +
+

Responses

+

200

+ +

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{appId}/token

+

Login with App-User or Application credentials.

+

Parameters

+

    +
  • login-credentials (LoginCredentials) +Login credentials either username/password or id/secret. (Specified +in body).
  • +
+

Responses

+

200

+ +

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+
+
+

Activities

+

GET /{orgId}/{appId}/groups/{groupId}/feed

+

Get a group’s feed through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • groupId (string) One of the group’s identification which includes +name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of group’s activity.
  • +
  • Schema: ActivityFeed
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{appId}/users/{userId}/activities

+

Create an activity in the activities collection.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • userId-3 (string) One of the user’s identification which includes +username or UUID. (Specified in path).
  • +
  • CreateActivity (CreateActivity) One or more +sets of activity properties. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of user’s activity.
  • +
  • Schema: ActivityFeed
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{appId}/users/{userId}/feed

+

Retrieve a user’s feed through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • userId-3 (string) One of the user’s identification which includes +username or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of user’s activity feed.
  • +
  • Schema: ActivityFeed
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+
+
+

Admin-Users

+

GET /management/orgs/{orgId}/users

+

Retrieve details about the admin users in an organization.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved Admin user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

DELETE /management/orgs/{orgId}/users/{userId}

+

Remove an admin user from an organization through providing both Id of +application and organization.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • userId-2 (string) One of the user’s identification which includes +username, email address or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of deleted Admin user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /management/users

+

Create a whole new admin user.

+

Parameters

+

    +
  • CreateAdminUser (CreateAdminUser) User +entity with fields required for User creation. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An API Response with a entities array containing the +newly created Admin User.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/users/resetpw

+

Initiate the reset of an admin user’s password.

+

Parameters

+

+ + +

Responses

+

200

+
    +
  • Description: An array of complete messages.
  • +
  • Schema: Action
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /management/users/resetpw

+

Complete the password reset through getting the newpassword and the old +one for identification.

+

Parameters

+

    +
  • ResetPWMsg (ResetPWMsg) Parameters and value +for the Captcha challenge, the admin user’s response to the Captcha +challenge, and the admin user’s email address. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of complete messages.
  • +
  • Schema: ` <#>`__
  • +
+

default

+
    +
  • Description:
  • +
  • Schema: Error
  • +
+

GET /management/users/{userId}

+

Retrieve details about an admin user.

+

Parameters

+

    +
  • userId (string) One of the user’s identification which includes +username, real name, email address or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An API Response with a entities array containing the +Admin User.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

PUT /management/users/{userId}

+

Update the info of an admin user.

+

Parameters

+

    +
  • userId (string) One of the user’s identification which includes +username, real name, email address or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An API Response with a entities array containing the +updated Admin User
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/users/{userId}/activate

+

Activate an admin user from a link provIded in an email notification.

+

Parameters

+

    +
  • userId (string) One of the user’s identification which includes +username, real name, email address or UUID. (Specified in path).
  • +
  • token (string) Activation token’s query statement. (Specified in +query).
  • +
  • confirm_email (boolean) Query statement of whether send +confimation email or not. (Specified in query).
  • +
+

Responses

+

200

+
    +
  • Description: An array of complete messages.
  • +
  • Schema: Action
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

PUT /management/users/{userId}/password

+

Update an admin user’s password through getting the newpassword and the +old one for identification.

+

Parameters

+

    +
  • userId (string) One of the user’s identification which includes +username, real name, email address or UUID. (Specified in path).
  • +
  • ResetPW (ResetPW) The user’s old and new password. +(Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of complete messages.
  • +
  • Schema: Action
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/users/{userId}/reactivate

+

Reactivate an expired admin user.

+

Parameters

+

    +
  • userId (string) One of the user’s identification which includes +username, real name, email address or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of complete messages.
  • +
  • Schema: Action
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+
+
+

App-Users

+

GET /{orgId}/{appId}/users

+

Retrieve users though query statement.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • queryStatement (string) The query statement of the User. +(Specified in query).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{appId}/users

+

Create a user in the users collection through providing all the +identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • CreateUser (CreateUser) The properties of the +user. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{appId}/users/{userId}

+

Retrieve a user through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • userId-2 (string) One of the user’s identification which includes +username, email address or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

PUT /{orgId}/{appId}/users/{userId}

+

Update a user through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • userId-3 (string) One of the user’s identification which includes +username or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of updated user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

DELETE /{orgId}/{appId}/users/{userId}

+

Remove a user through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • userId-3 (string) One of the user’s identification which includes +username or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of deleted user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{appId}/users/{user}/password

+

Set a user’s password or reset the user’s existing password.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • username (string) The username of the user. (Specified in path).
  • +
  • ResetPW (ResetPW) The user’s old and new password. +(Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of complete messages.
  • +
  • Schema: Action
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+
+
+

Entities-Collections

+

GET /{orgId}/{appId}/users/{userId}/{relation}

+

Retrieve a user’s collections or connections through query statement.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • userId-3 (string) One of the user’s identification which includes +username or UUID. (Specified in path).
  • +
  • relation (string) The relation between user and collections. +(Specified in path).
  • +
  • queryStatement (string) The query statement of the user. +(Specified in query).
  • +
+

Responses

+

200

+
    +
  • Description: An array of user’s collections info.
  • +
  • Schema: Entity
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{appId}/{collectionId}

+

Retrieve collection through query statement.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • collectionId (string) One of the collection’s identification +which includes name or uuid. (Specified in path).
  • +
  • queryStatement (string) Any values specified in the query +statement should be enclosed in single-quotes. (Specified in query).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved collection’s info.
  • +
  • Schema: Entity
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

PUT /{orgId}/{appId}/{collectionId}

+

Update collection through query statement.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • collectionId (string) One of the collection’s identification +which includes name or uuid. (Specified in path).
  • +
  • queryStatement (string) Any values specified in the query +statement should be enclosed in single-quotes. (Specified in query).
  • +
+

Responses

+

200

+
    +
  • Description: An array of updated collection’s info.
  • +
  • Schema: Entity
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{appId}/{collectionId}/{entityId1}/{relation}/{entityId2}

+

Add an entity to a collection through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • collectionId (string) One of the collection’s identification +which includes name or uuid. (Specified in path).
  • +
  • entityId1 (string) The Id of the 1st entity. (Specified in path).
  • +
  • relation (string) The relation between 1st entity and 2nd entity. +(Specified in path).
  • +
  • entityId2 (string) The Id of the 2nd entity. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of added entity’s info.
  • +
  • Schema: Entity
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

DELETE +/{orgId}/{appId}/{collectionId}/{entityId1}/{relation}/{entityId2}

+

Remove an entity from a collection through providing all the +identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • collectionId (string) One of the collection’s identification +which includes name or uuid. (Specified in path).
  • +
  • entityId1 (string) The Id of the 1st entity. (Specified in path).
  • +
  • relation (string) The relation between 1st entity and 2nd entity. +(Specified in path).
  • +
  • entityId2 (string) The Id of the 2nd entity. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of deleted entity’s info.
  • +
  • Schema: Entity
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{appId}/{collectionId}/{entityId}

+

Retrieve an entity through providing Id of application, organization, +collection and entity.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • collectionId (string) One of the collection’s identification +which includes name or uuid. (Specified in path).
  • +
  • entityId (string) One of the entity’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved entity’s info.
  • +
  • Schema: Entity
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

PUT /{orgId}/{appId}/{collectionId}/{entityId}

+

One or more properties can be updated with a single request.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • collectionId (string) One of the collection’s identification +which includes name or uuid. (Specified in path).
  • +
  • entityId (string) One of the entity’s identification which +includes name or uuid. (Specified in path).
  • +
  • entityproperty (CreateEntities) The +properties of the entity. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of updated entity’s info.
  • +
  • Schema: Entity
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

DELETE /{orgId}/{appId}/{collectionId}/{entityId}

+

Delete an entity from the collection.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • collectionId (string) One of the collection’s identification +which includes name or uuid. (Specified in path).
  • +
  • entityId (string) One of the entity’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of deleted entity’s info.
  • +
  • Schema: Entity
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{appId}/{entitytype}

+

When a new entity is created, Usergrid will automatically create a +corresponding collection if one does not already exist. The collection +will automatically be named with the plural form of the entity type.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • entitytype (string) The entity type to create. (Specified in +path).
  • +
  • entityproperty (CreateEntities) The +properties of the entity. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created custom entity’s info.
  • +
  • Schema: Entity
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+
+
+

Events

+

POST /{orgId}/{appId}/events

+

Create an event through providing both Id of organization and +application.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • CreateEvent (CreateEvent) The required +property of the event. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created event’s info.
  • +
  • Schema: Event
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+
+
+

Groups

+

POST /{orgId}/{appId}/groups

+

Create a new group through providing both Id of organization and +application.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • groupproperty (CreateGroup) The property of +the created group. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created group’s info.
  • +
  • Schema: Group
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{appId}/groups/{groupId}/activities

+

Create an activity to a specific group. In this case the activity is +created in the activities collection and is accessible at the +/activities endpoint to users who have the permission to read that +endpoint. In addition, a relationship is established between the +activity and the group, and because of that, the activity will appear in +the group’s feed. The group ‘owns’ the activity. Also, the activity will +be published in the feed of all users that are members of the group.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • groupId (string) One of the group’s identification which includes +name or uuid. (Specified in path).
  • +
  • CreateActivity (CreateActivity) One or more +sets of activity properties. (Specified in body).
  • +
+

Responses

+

200

+ +

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{appId}/groups/{groupId}/users/{userId}

+

Add a user to a group through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • groupId (string) One of the group’s identification which includes +name or uuid. (Specified in path).
  • +
  • userId-3 (string) One of the user’s identification which includes +username or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of added user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

DELETE /{orgId}/{appId}/groups/{groupId}/users/{userId}

+

Delete user from a group through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • groupId (string) One of the group’s identification which includes +name or uuid. (Specified in path).
  • +
  • userId-3 (string) One of the user’s identification which includes +username or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of deleted user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{org_Id}/{app_Id}/groups/{groupId}

+

Get a group through through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • groupId (string) One of the group’s identification which includes +name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved group’s info.
  • +
  • Schema: Group
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

PUT /{org_Id}/{app_Id}/groups/{groupId}

+

Update a group through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • groupId (string) One of the group’s identification which includes +name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of updated group’s info.
  • +
  • Schema: Group
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+
+
+

Notifications

+

POST /{orgId}/{applicationId}/devices

+

Create notifications for user through targeting by location and +providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
  • notification (CreateNotifications) +These parameters are used when forming the notification portion of +the request. (Specified in body).
  • +
  • queryStatement (string) The query statement of the location of +the user. (Specified in query).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created notification’s info.
  • +
  • Schema: Notification
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{applicationId}/devices/*/notifications

+

Create notifications for all devices. This request will target all +device entities.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
  • notification (CreateNotifications) +These parameters are used when forming the notification portion of +the request. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created notification’s info.
  • +
  • Schema: Notification
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{applicationId}/devices/{deviceId}/notifications

+

Create notifications for a single device. This request will target a +specific device entity.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
  • deviceId (string) One of the device’s identification which +includes name or uuid. (Specified in path).
  • +
  • notification (CreateNotifications) +These parameters are used when forming the notification portion of +the request. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created notification’s info.
  • +
  • Schema: Notification
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{applicationId}/groups/{path}/notifications

+

Create notifications for a group. This request will target all users +associated with a specific group entity.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • path (string) The path of the group. (Specified in path).
  • +
  • notification (CreateNotifications) +These parameters are used when forming the notification portion of +the request. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created notification’s info.
  • +
  • Schema: Notification
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{applicationId}/notifications

+

Retrieve one or more notifications through providing all the +identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved notification’s info.
  • +
  • Schema: Notification
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

PUT /{orgId}/{applicationId}/notifications/{notificationId}

+

Update a Notification in order to cancel the notifcation or set a new +expiration time.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
  • notificationId (string) One of the notification’s identification +which includes name or uuid. (Specified in path).
  • +
  • notificationUpdate (NotificationUpdate) +Object with Notification fields to be updated. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An API Response object containing an entity of type +Notification.
  • +
  • Schema: Notification
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

DELETE /{orgId}/{applicationId}/notifications/{notificationId}

+

Delete an unsent Notification from the system.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
  • notificationId (string) One of the notification’s identification +which includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: API Response containing Notification entity that was +deleted.
  • +
  • Schema: Notification
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{applicationId}/receipts

+

Retrieve one or more receipts through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved receipt’s info.
  • +
  • Schema: Receipt
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{applicationId}/users/{userId}/notifications

+

Create notifications for a user. This request will target a specific +user entity.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
  • userId-3 (string) One of the user’s identification which includes +username or UUID. (Specified in path).
  • +
  • notification (CreateNotifications) +These parameters are used when forming the notification portion of +the request. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created notification’s info.
  • +
  • Schema: Notification
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{applicationId}/{deviceId}/*/receipts

+

Retrieve receipts associated with one or more devices through providing +all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
  • deviceId (string) One of the device’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved receipt’s info.
  • +
  • Schema: Receipt
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{applicationId}/{notificationId}/*/queue

+

Retrieve the list of devices associated with one or more notifications +before the notifications are sent through providing all the +identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
  • notificationId (string) One of the notification’s identification +which includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved device’s info.
  • +
  • Schema: Device
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{applicationId}/{notificationId}/*/receipts

+

Retrieve receipts for one or more notifications through providing all +the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
  • notificationId (string) One of the notification’s identification +which includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved receipt’s info.
  • +
  • Schema: Receipt
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{applicationId}/{receiptId}/*/notifications

+

Retrieve notifications associated with one or more receipts through +providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • applicationId (string) One of the application’s identification +which includes name or uuid (same as appId). (Specified in path).
  • +
  • receiptId (string) One of the receipt’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved notification’s info.
  • +
  • Schema: Notification
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+
+
+

Organizations-Applications

+

POST /management/orgs

+

Create an organization through a form post.

+

Parameters

+

    +
  • CreateOrg (CreateOrg) A set of organization +properties supplied through a form. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created Organization.
  • +
  • Schema: Organization
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/orgs/{orgId}

+

Retrieve an organization given a specified UUID or username.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created Organization.
  • +
  • Schema: Organization
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/orgs/{orgId}/activate

+

Activate an organization from a link provIded in an email notification.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • token (string) Activation token. (Specified in query).
  • +
  • confirm_email (boolean) Send confirmation email or not. +(Specified in query).
  • +
+

Responses

+

200

+
    +
  • Description: An array of complete messages.
  • +
  • Schema: Action
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/orgs/{orgId}/apps

+

Retrieve the applications in an organization through providing both Id +of application and organization.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved application data.
  • +
  • Schema: AppData
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

DELETE /management/orgs/{orgId}/apps/{appId}

+

Remove an application from an organization through providing both Id of +application and organization.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of deleted application info.
  • +
  • Schema: AppData
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/orgs/{orgId}/apps/{appId}/credentials

+

Retrieve the client Id and client secret credentials for an application +in an organization.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved credentials info.
  • +
  • Schema: Credential
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /management/orgs/{orgId}/apps/{appId}/credentials

+

Generate the client Id and client secret credentials for an application +in an organization.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of generated credentials info.
  • +
  • Schema: Credential
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/orgs/{orgId}/credentials

+

Retrieve the credentials for an organization client.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of Credential
  • +
  • Schema: Credential
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /management/orgs/{orgId}/credentials

+

Generate whole new credentials for an organization client.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of Credential
  • +
  • Schema: Credential
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/orgs/{orgId}/feed

+

Retrieve an organization’s activity feed.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of the organization’s ActivityFeed.
  • +
  • Schema: ActivityFeed
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/orgs/{orgId}/reactivate

+

Reactivate an expired organization.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of complete messages.
  • +
  • Schema: Action
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /management/users/{userId}/feed

+

Retrieve an admin user’s activity feed.

+

Parameters

+

    +
  • userId (string) One of the user’s identification which includes +username, real name, email address or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of user’s activity
  • +
  • Schema: ActivityFeed
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+
+
+

Permissions-Roles

+

GET /{orgId}/{appId}/roles

+

Retrieve the roles in an application through providing all the +identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of retrieved role’s info.
  • +
  • Schema: Role
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{appId}/roles

+

Create a new role through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • roleproperty (AddRole) The required properties of +the role. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: An array of created role’s info.
  • +
  • Schema: Role
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

DELETE /{orgId}/{appId}/roles/{roleId}/permissions

+

Remove permissions from a role.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • roleId (string) One of the role’s identification which includes +name or uuid. (Specified in path).
  • +
  • Permissions (Permissions) The query statement +of the url pattern. (Specified in body).
  • +
+

Responses

+

200

+
    +
  • Description: Permissions object with array of the deleated Usergrid +Permission strings.
  • +
  • Schema: Permissions
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{appId}/roles/{roleId}/users

+

Retrieve the users in a role through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • roleId (string) One of the role’s identification which includes +name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An API Response with a entities array of Users.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{appId}/roles/{roleId}/users/{userId}

+

Add a user to a role through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • roleId (string) One of the role’s identification which includes +name or uuid. (Specified in path).
  • +
  • userId-3 (string) One of the user’s identification which includes +username or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of added user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

DELETE /{orgId}/{appId}/roles/{roleId}/users/{userId}

+

Remove a user from a role through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • roleId (string) One of the role’s identification which includes +name or uuid. (Specified in path).
  • +
  • userId-3 (string) One of the user’s identification which includes +username or UUID. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of deleted user’s info.
  • +
  • Schema: User
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

DELETE /{orgId}/{appId}/roles/{rolename}

+

Remove a role through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • rolename (string) The name of the role. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: An array of deleted role’s info.
  • +
  • Schema: Role
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

GET /{orgId}/{applicationId}/roles/{roleId}/permissions

+

Retrieve permissions for a Role.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • roleId (string) One of the role’s identification which includes +name or uuid. (Specified in path).
  • +
+

Responses

+

200

+
    +
  • Description: Permissions object with array of Usergrid Permission +strings.
  • +
  • Schema: Permissions
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+

POST /{orgId}/{applicationId}/roles/{roleId}/permissions

+

Add permissions to a role through providing all the identifications.

+

Parameters

+

    +
  • orgId (string) One of the organization’s identification which +includes name or uuid. (Specified in path).
  • +
  • appId (string) One of the application’s identification which +includes name or uuid. (Specified in path).
  • +
  • roleId (string) One of the role’s identification which includes +name or uuid. (Specified in path).
  • +
  • Permissions (Permissions) Permissions object +with array of Usergrid Permission strings to be added. (Specified in +body).
  • +
+

Responses

+

200

+
    +
  • Description: Permissions object with array of Usergrid Permission +strings.
  • +
  • Schema: Permission
  • +
+

default

+
    +
  • Description: Unexpected error.
  • +
  • Schema: Error
  • +
+
+
+
+

Models

+

This section lists the properties for the Usergrid Default Entities:

+
+

AccessTokenResponse

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

access_token

+

string

+

Access-token that may be used on subsequent requests.

+

false

+

expires_in

+

number

+

Time (in milliseconds) until access-token expires.

+

false

+

user

+

User

+

User object if login was done as a user.

+

false

+
+
+

Action

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

action

+

string

+

The requested action.

+

false

+

status

+

string

+

The status of the requested action.

+

false

+

timestamp

+

number

+

The timestamp of the requested action.

+

false

+

duration

+

number

+

The duration of the requested action.

+

false

+

token

+

string

+

The token required for getting an AdminUser.

+

false

+

Referring Definitions

+ +
+
+

ActivityFeed

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

entityproperty

+

Entity

+

false

+

category

+

string

+

The category of the activity.

+

false

+

metadataproperty

+

Metadata

+

false

+

objectproperty

+

Object

+

false

+

title

+

string

+

The title of the activity.

+

false

+

verb

+

string

+

The verb of the activity.

+

false

+

published

+

number

+

UTC timestamp of the feed publish time.

+

false

+

completeMsg

+

Action

+

false

+
+
+

AddRole

+

Properties

+ + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

title

+

string

+

The title of the role.

+

true

+

role name

+

string

+

The name of the role.

+

true

+
+
+

AppData

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

tester/sandbox

+

string

+

The UUID of tester/sandbox.

+

false

+

tester/app1

+

string

+

The UUID of tester/app1.

+

false

+

tester/app2

+

string

+

The UUID of tester/app2.

+

false

+

completeMsg

+

Action

+

false

+

Referring Definitions

+ +
+
+

CreateActivity

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

displayName

+

string

+

true

+

uuid

+

string

+

true

+

username

+

string

+

true

+

image

+

ImageModel

+

false

+

verb

+

string

+

true

+

content

+

string

+

true

+
+
+

CreateAdminUser

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

username

+

string

+

true

+

email

+

string

+

false

+

name

+

string

+

false

+

password

+

string

+

false

+
+
+

CreateEntities

+

Properties

+ + + + + + + +

Name

+

Type

+

Description

+

Required

+
+
+

CreateEvent

+

Properties

+ + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

timestamp

+

string

+

true

+
+
+

CreateGroup

+

Properties

+ + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

title

+

string

+

The title of the group.

+

true

+

path

+

string

+

The path of the group.

+

true

+
+
+

CreateNotifications

+

An array of Notifications to be created.

+

Properties

+ + + + + + + +

Name

+

Type

+

Description

+

Required

+
+
+

CreateOrg

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

organization

+

string

+

true

+

username

+

string

+

true

+

name

+

string

+

true

+

email

+

string

+

true

+

password

+

string

+

true

+
+
+

CreateUser

+

Properties

+ + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

username

+

string

+

true

+
+
+

Credential

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

client_Id

+

string

+

The Id of the client.

+

false

+

client_secret

+

string

+

The secret of the client.

+

false

+

completeMsg

+

Action

+

false

+
+
+

Device

+

Represents a single Device that is registered for recieving of Push +Notifications.

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

uuid

+

string

+

Unique entity Id.

+

false

+

type

+

string

+

Type of entity.

+

false

+

name

+

string

+

Notifier display name.

+

false

+

created

+

number

+

UTC timestamp in milliseconds of when the entity was created.

+

false

+

modified

+

number

+

UTC timestamp in milliseconds of when the entity was last modified.

+

false

+

metadata

+

Metadata

+

false

+

completeMsg

+

Action

+

false

+
+
+

Entity

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

uuid

+

string

+

The UUID of the entity.

+

false

+

type

+

string

+

The type of the entity.

+

false

+

created

+

number

+

UTC timestamp of entity creation time.

+

false

+

modified

+

Actor

+

UTC timestamp of entity modified time.

+

false

+

metadata

+

Metadata

+

false

+

name

+

string

+

The name of the entity.

+

false

+

message

+

string

+

false

+

Referring Definitions

+ +
+
+

Error

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

code

+

integer

+

false

+

message

+

string

+

false

+

fields

+

object

+

false

+
+
+

Event

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

applicationName

+

string

+

The application name of the event.

+

false

+

entity

+

Entity

+

false

+

url

+

string

+

The url of the event.

+

false

+

applicationId

+

string

+

The application UUID of the event.

+

false

+

parameters

+

string

+

The parameters of the event.

+

false

+

organization

+

string

+

The title of the organization.

+

false

+

completeMsg

+

Action

+

false

+
+
+

Group

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

uuid

+

string

+

The UUID of the group.

+

false

+

type

+

string

+

The type of the group.

+

false

+

created

+

string

+

The created Id for the group.

+

false

+

modified

+

string

+

The modified Id for the group.

+

false

+

path

+

string

+

The path of the group.

+

false

+

metadata

+

Metadata

+

false

+

title

+

string

+

The title of the group.

+

false

+

completeMsg

+

Action

+

false

+
+
+

LoginCredentials

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

grant_type

+

string

+

Grant-type must be ‘password’ or ‘client_credentials’.

+

false

+

username

+

string

+

Username of user attempting login, required only if grant_type is +‘password’.

+

false

+

password

+

string

+

Password of user attempting login, required only if grant_type is +‘password’.

+

false

+

client_id

+

string

+

Client-ID portion of credentials, required only if grant_type is +‘client_credentials’.

+

false

+

client_secret

+

string

+

Client-Secret portion of credentials, required only if grant_type is +‘client_credentials’.

+

false

+
+
+

Notification

+

Represents a Push Notification that is either scheduled, finished or +cancelled.

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

uuid

+

string

+

Unique entity Id.

+

false

+

type

+

string

+

Type of entity.

+

false

+

created

+

number

+

UTC timestamp in milliseconds of when the entity was created.

+

false

+

modified

+

number

+

UTC timestamp in milliseconds of when the entity was last modified.

+

false

+

payloads

+

string

+

The push notifications to be delivered.

+

true

+

errorMessage

+

string

+

Error message returned by the notification service (APNs or GCM) if the +notification fails entirely.

+

false

+

scheduled

+

boolean

+

Whether the notification is currently scheduled for delivery.

+

false

+

state

+

string

+

The current delivery status of the notification ‘FINISHED’, ‘SCHEDULED’ +or ‘CANCELED’.

+

false

+

metadata

+

Metadata

+

false

+

completeMsg

+

Action

+

false

+
+
+

NotificationUpdate

+

Represents fields that may be updated on a Notification to cause changes +in Push Notification processing.

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

canceled

+

boolean

+

Setting this field to true will cancel a Notification, if it has not yet +been sent.

+

false

+

deliver

+

number

+

Specifies the UNIX timestamp time at which the Notification should be +sent.

+

false

+

expired

+

number

+

Specifies the UNIX timestamp time at which this Notification has +expired.

+

false

+
+
+

Organization

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

applicationId

+

string

+

The application Id of the owner.

+

false

+

username

+

string

+

The username of the owner.

+

false

+

name

+

string

+

The name of the owner.

+

false

+

email

+

string

+

The email of the owner.

+

false

+

activated

+

boolean

+

Indicate whether the account is activated or not.

+

false

+

disabled

+

boolean

+

Indicate whether the account is disabled or not.

+

false

+

uuid

+

string

+

The UUID of the owner.

+

false

+

adminUser

+

boolean

+

Indicate whether the use is a adminUser or not.

+

false

+

displayEmail

+

string

+

The display of the email of the owner.

+

false

+

htmldisplayEmail

+

string

+

The HTML display of the email of the owner.

+

false

+

orgname

+

string

+

The name of the organization.

+

false

+

orguuId

+

string

+

The UUID of the organization.

+

false

+

applicationdata

+

AppData

+

false

+

completeMsg

+

Action

+

false

+
+
+

Permissions

+

Represents a set of Permissions associated with a User or a Role, each +being a Usergrid Permission String.

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

application

+

string

+

The UUID of the associated application.

+

false

+

applicationName

+

string

+

The name of the associated application.

+

false

+

organization

+

string

+

The name of the associated organization.

+

false

+

data

+

array

+

Array of strings each being a Usergrid Permission String.

+

true

+
+
+

Receipt

+

Represents response received from Notification service indicating +success or failure.

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

uuid

+

string

+

Unique entity Id.

+

false

+

type

+

string

+

Type of entity.

+

false

+

created

+

number

+

UTC timestamp in milliseconds of when the entity was created.

+

false

+

modified

+

number

+

UTC timestamp in milliseconds of when the entity was last modified.

+

false

+

payloads

+

string

+

The push notifications to be delivered.

+

false

+

errorMessage

+

string

+

Error message returned by the notification service (APNs or GCM) if the +notification fails entirely.

+

false

+

errorCode

+

string

+

Error code returned by the notification service.

+

false

+

sent

+

number

+

UTC timestamp in milliseconds for when the notification was sent.

+

false

+

metadata

+

Metadata

+

false

+

completeMsg

+

Action

+

false

+
+
+

ResetPW

+

Properties

+ + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

password

+

string

+

true

+

newpassword

+

string

+

true

+
+
+

ResetPWMsg

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

recaptcha_response

+

string

+

Parameters and value for the Captcha challenge.

+

true

+

recaptcha_challenge

+

string

+

The admin user’s response to the Captcha challenge.

+

true

+

email

+

string

+

true

+
+
+

Role

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

applicationName

+

string

+

The application name of the event.

+

false

+

count

+

number

+

The numebr of the roles.

+

false

+

entity

+

Entity

+

false

+

url

+

string

+

The url of the event.

+

false

+

applicationId

+

string

+

The application UUID of the event.

+

false

+

parameters

+

string

+

The parameters of the event.

+

false

+

organization

+

string

+

The title of the organization.

+

false

+

completeMsg

+

Action

+

false

+

path

+

string

+

The path of the role.

+

false

+
+
+

User

+

Represents a User account which may be a user within an Application’s +User collection, or may be an Admin User.

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

applicationId

+

string

+

The application Id of a user.

+

false

+

username

+

string

+

The username of a user.

+

false

+

name

+

string

+

The name of a user.

+

false

+

email

+

string

+

The email of a user.

+

false

+

activated

+

boolean

+

Indicate whether the account is activated or not.

+

false

+

disabled

+

boolean

+

Indicate whether the account is disabled or not.

+

false

+

uuid

+

string

+

The UUID of a user.

+

false

+

adminUser

+

boolean

+

Indicate whether the use is a adminUser or not.

+

false

+

displayEmail

+

string

+

The display of the email of a user.

+

false

+

htmldisplayEmail

+

string

+

The HTML display of the email of a user.

+

false

+

organization

+

string

+

The organization of the user.

+

false

+

picture

+

string

+

The uri of the user’s picture.

+

false

+

uri

+

string

+

The uri of the user.

+

false

+

path

+

string

+

The path of the user.

+

false

+

completeMsg

+

Action

+

false

+

Referring Definitions

+ +
+
+
+

Sub-Types

+

This section lists the properties for sub-types used in Usergrid Default +Entities.

+
+

Collections

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

activities

+

string

+

false

+

feed

+

string

+

false

+

roles

+

string

+

false

+

users

+

string

+

false

+

Referring Definitions

+ +
+
+

ImageModel

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

duration

+

number

+

false

+

height

+

number

+

false

+

url

+

string

+

false

+

wIdth

+

integer

+

false

+

email

+

string

+

false

+

Referring Definitions

+ +
+
+

Metadata

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

cursor

+

string

+

The cursor of the metadata.

+

false

+

path

+

string

+

The path of the metadata.

+

false

+

sets

+

Sets

+

false

+

collections

+

Collections

+

false

+

Referring Definitions

+ +
+
+

Object

+

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

displayname

+

string

+

The display of the name of the object.

+

false

+

objecttype

+

string

+

The type of the object.

+

false

+

objectuuId

+

string

+

The UUID of the object.

+

false

+

entitytype

+

string

+

The entitytype of the object.

+

false

+

Referring Definitions

+ +
+
+

Sets

+

Properties

+ + + + + + + + + + + + + + + + + + + +

Name

+

Type

+

Description

+

Required

+

rolenames

+

string

+

false

+

permissions

+

string

+

false

+

Referring Definitions

+ +
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/rest-endpoints/api-reference.html b/content/docs/rest-endpoints/api-reference.html new file mode 100644 index 0000000000..c4841f9ea8 --- /dev/null +++ b/content/docs/rest-endpoints/api-reference.html @@ -0,0 +1,5273 @@ + + + Usergrid API Reference + + + + + + + + + + + + +
+
+
+ +

Usergrid API Reference

+

Generated from Swagger.

+

Methods

API methods are organized by the tags.

+

Following the methods is a listing of all Default Entity Models.

+ +

Access-Tokens

+ +
+ +
+

POST /management/token + +

+
+ +
+ +

Login with Admin-User or Organization credentials.

+ +

Parameters

+ +
    +
  • + login-credentials ( LoginCredentials)
    + Login credentials either username/password or id/secret. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 + +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /{orgId}/{appId}/token + +

+
+ +
+ +

Login with App-User or Application credentials.

+ +

Parameters

+ +
    +
  • + login-credentials ( LoginCredentials)
    + Login credentials either username/password or id/secret. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of new created Admin user's info.
    • +
    • Schema: [AccessTokenReponse]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +

Activities

+ +
+ +
+

GET /{orgId}/{appId}/groups/{groupId}/feed + +

+
+ +
+ +

Get a group's feed through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + groupId (string)
    + One of the group's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of group's activity.
    • +
    • Schema: [ActivityFeed]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /{orgId}/{appId}/users/{userId}/activities + +

+
+ +
+ +

Create an activity in the activities collection.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-3 (string)
    + One of the user's identification which includes username or UUID. (Specified in path). +
  • +
  • + CreateActivity ( CreateActivity)
    + One or more sets of activity properties. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of user's activity.
    • +
    • Schema: [ActivityFeed]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /{orgId}/{appId}/users/{userId}/feed + +

+
+ +
+ +

Retrieve a user's feed through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-3 (string)
    + One of the user's identification which includes username or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of user's activity feed.
    • +
    • Schema: [ActivityFeed]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +

Admin-Users

+ +
+ +
+

GET /management/orgs/{orgId}/users + +

+
+ +
+ +

Retrieve details about the admin users in an organization.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of retrieved Admin user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

DELETE /management/orgs/{orgId}/users/{userId} + +

+
+ +
+ +

Remove an admin user from an organization through providing both Id of application and organization.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-2 (string)
    + One of the user's identification which includes username, email address or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of deleted Admin user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /management/users + +

+
+ +
+ +

Create a whole new admin user.

+ +

Parameters

+ +
    +
  • + adminuserproperty ( CreateAdminUser)
    + One or more sets of user properties of which username is mandatory and must be unique. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of new created Admin user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/users/resetpw + +

+
+ +
+ +

Initiate the reset of an admin user's password.

+ +

Parameters

+ +
    +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of complete messages.
    • +
    • Schema: [Action]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /management/users/resetpw + +

+
+ +
+ +

Complete the password reset through getting the newpassword and the old one for identification.

+ +

Parameters

+ +
    +
  • + ResetPWMsg ( ResetPWMsg)
    + Parameters and value for the Captcha challenge, the admin user's response to the Captcha challenge, and the admin user's email address. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of complete messages.
    • +
    • Schema: [Action]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/users/{userId} + +

+
+ +
+ +

Retrieve details about an admin user.

+ +

Parameters

+ +
    +
  • + userId (string)
    + One of the user's identification which includes username, real name, email address or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of user's details
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

PUT /management/users/{userId} + +

+
+ +
+ +

Update the info of an admin user.

+ +

Parameters

+ +
    +
  • + userId (string)
    + One of the user's identification which includes username, real name, email address or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of user's details.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/users/{userId}/activate + +

+
+ +
+ +

Activate an admin user from a link provIded in an email notification.

+ +

Parameters

+ +
    +
  • + userId (string)
    + One of the user's identification which includes username, real name, email address or UUID. (Specified in path). +
  • +
  • + token (string)
    + Activation token's query statement. (Specified in query). +
  • +
  • + confirm_email (boolean)
    + Query statement of whether send confimation email or not. (Specified in query). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of complete messages.
    • +
    • Schema: [Action]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

PUT /management/users/{userId}/password + +

+
+ +
+ +

Update an admin user's password through getting the newpassword and the old one for identification.

+ +

Parameters

+ +
    +
  • + userId (string)
    + One of the user's identification which includes username, real name, email address or UUID. (Specified in path). +
  • +
  • + ResetPW ( ResetPW)
    + The user's old and new password. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of complete messages.
    • +
    • Schema: [Action]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/users/{userId}/reactivate + +

+
+ +
+ +

Reactivate an expired admin user.

+ +

Parameters

+ +
    +
  • + userId (string)
    + One of the user's identification which includes username, real name, email address or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of complete messages.
    • +
    • Schema: [Action]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +

App-Users

+ +
+ +
+

GET /{orgId}/{appId}/users + +

+
+ +
+ +

Retrieve users though query statement.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + queryStatement (string)
    + The query statement of the User. (Specified in query). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of retrieved user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /{orgId}/{appId}/users + +

+
+ +
+ +

Create a user in the users collection through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + CreateUser ( CreateUser)
    + The properties of the user. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of created user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /{orgId}/{appId}/users/{userId} + +

+
+ +
+ +

Retrieve a user through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-2 (string)
    + One of the user's identification which includes username, email address or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of retrieved user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

PUT /{orgId}/{appId}/users/{userId} + +

+
+ +
+ +

Update a user through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-3 (string)
    + One of the user's identification which includes username or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of updated user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

DELETE /{orgId}/{appId}/users/{userId} + +

+
+ +
+ +

Remove a user through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-3 (string)
    + One of the user's identification which includes username or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of deleted user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /{orgId}/{appId}/users/{user}/password + +

+
+ +
+ +

Set a user's password or reset the user's existing password.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + username (string)
    + The username of the user. (Specified in path). +
  • +
  • + ResetPW ( ResetPW)
    + The user's old and new password. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of complete messages.
    • +
    • Schema: [Action]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +

Entities-Collections

+ +
+ +
+

GET /{orgId}/{appId}/users/{userId}/{relation} + +

+
+ +
+ +

Retrieve a user's collections or connections through query statement.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-3 (string)
    + One of the user's identification which includes username or UUID. (Specified in path). +
  • +
  • + relation (string)
    + The relation between user and collections. (Specified in path). +
  • +
  • + queryStatement (string)
    + The query statement of the user. (Specified in query). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of user's collections info.
    • +
    • Schema: [Entity]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /{orgId}/{appId}/{collectionId} + +

+
+ +
+ +

Retrieve collection through query statement.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + collectionId (string)
    + One of the collection's identification which includes name or uuid. (Specified in path). +
  • +
  • + queryStatement (string)
    + Any values specified in the query statement should be enclosed in single-quotes. (Specified in query). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of retrieved collection's info.
    • +
    • Schema: [Entity]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

PUT /{orgId}/{appId}/{collectionId} + +

+
+ +
+ +

Update collection through query statement.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + collectionId (string)
    + One of the collection's identification which includes name or uuid. (Specified in path). +
  • +
  • + queryStatement (string)
    + Any values specified in the query statement should be enclosed in single-quotes. (Specified in query). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of updated collection's info.
    • +
    • Schema: [Entity]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /{orgId}/{appId}/{collectionId}/{entityId1}/{relation}/{entityId2} + +

+
+ +
+ +

Add an entity to a collection through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + collectionId (string)
    + One of the collection's identification which includes name or uuid. (Specified in path). +
  • +
  • + entityId1 (string)
    + The Id of the 1st entity. (Specified in path). +
  • +
  • + relation (string)
    + The relation between 1st entity and 2nd entity. (Specified in path). +
  • +
  • + entityId2 (string)
    + The Id of the 2nd entity. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of added entity's info.
    • +
    • Schema: [Entity]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

DELETE /{orgId}/{appId}/{collectionId}/{entityId1}/{relation}/{entityId2} + +

+
+ +
+ +

Remove an entity from a collection through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + collectionId (string)
    + One of the collection's identification which includes name or uuid. (Specified in path). +
  • +
  • + entityId1 (string)
    + The Id of the 1st entity. (Specified in path). +
  • +
  • + relation (string)
    + The relation between 1st entity and 2nd entity. (Specified in path). +
  • +
  • + entityId2 (string)
    + The Id of the 2nd entity. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of deleted entity's info.
    • +
    • Schema: [Entity]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /{orgId}/{appId}/{collectionId}/{entityId} + +

+
+ +
+ +

Retrieve an entity through providing Id of application, organization, collection and entity.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + collectionId (string)
    + One of the collection's identification which includes name or uuid. (Specified in path). +
  • +
  • + entityId (string)
    + One of the entity's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of retrieved entity's info.
    • +
    • Schema: [Entity]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

PUT /{orgId}/{appId}/{collectionId}/{entityId} + +

+
+ +
+ +

One or more properties can be updated with a single request.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + collectionId (string)
    + One of the collection's identification which includes name or uuid. (Specified in path). +
  • +
  • + entityId (string)
    + One of the entity's identification which includes name or uuid. (Specified in path). +
  • +
  • + entityproperty ( CreateEntities)
    + The properties of the entity. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of updated entity's info.
    • +
    • Schema: [Entity]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

DELETE /{orgId}/{appId}/{collectionId}/{entityId} + +

+
+ +
+ +

Delete an entity from the collection.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + collectionId (string)
    + One of the collection's identification which includes name or uuid. (Specified in path). +
  • +
  • + entityId (string)
    + One of the entity's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of deleted entity's info.
    • +
    • Schema: [Entity]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /{orgId}/{appId}/{entitytype} + +

+
+ +
+ +

When a new entity is created, Usergrid will automatically create a corresponding collection if one does not already exist. The collection will automatically be named with the plural form of the entity type.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + entitytype (string)
    + The entity type to create. (Specified in path). +
  • +
  • + entityproperty ( CreateEntities)
    + The properties of the entity. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of created custom entity's info.
    • +
    • Schema: [Entity]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +

Events

+ +
+ +
+

POST /{orgId}/{appId}/events + +

+
+ +
+ +

Create an event through providing both Id of organization and application.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + CreateEvent ( CreateEvent)
    + The required property of the event. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of created event's info.
    • +
    • Schema: [Event]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +

Groups

+ +
+ +
+

POST /{orgId}/{appId}/groups + +

+
+ +
+ +

Create a new group through providing both Id of organization and application.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + groupproperty ( CreateGroup)
    + The property of the created group. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of created group's info.
    • +
    • Schema: [Group]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /{orgId}/{appId}/groups/{groupId}/activities + +

+
+ +
+ +

Create an activity to a specific group. In this case the activity is created in the activities collection and is accessible at the /activities endpoint to users who have the permission to read that endpoint. In addition, a relationship is established between the activity and the group, and because of that, the activity will appear in the group’s feed. The group 'owns' the activity. Also, the activity will be published in the feed of all users that are members of the group.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + groupId (string)
    + One of the group's identification which includes name or uuid. (Specified in path). +
  • +
  • + CreateActivity ( CreateActivity)
    + One or more sets of activity properties. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of user's activity.
    • +
    • Schema: [ActivityFeed]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /{orgId}/{appId}/groups/{groupId}/users/{userId} + +

+
+ +
+ +

Add a user to a group through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + groupId (string)
    + One of the group's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-3 (string)
    + One of the user's identification which includes username or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of added user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

DELETE /{orgId}/{appId}/groups/{groupId}/users/{userId} + +

+
+ +
+ +

Delete user from a group through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + groupId (string)
    + One of the group's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-3 (string)
    + One of the user's identification which includes username or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of deleted user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /{org_Id}/{app_Id}/groups/{groupId} + +

+
+ +
+ +

Get a group through through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + groupId (string)
    + One of the group's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of retrieved group's info.
    • +
    • Schema: [Group]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

PUT /{org_Id}/{app_Id}/groups/{groupId} + +

+
+ +
+ +

Update a group through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + groupId (string)
    + One of the group's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of updated group's info.
    • +
    • Schema: [Group]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +

Organizations-Applications

+ +
+ +
+

POST /management/orgs + +

+
+ +
+ +

Create an organization through a form post.

+ +

Parameters

+ +
    +
  • + CreateOrg ( CreateOrg)
    + A set of organization properties supplied through a form. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of created Organization.
    • +
    • Schema: [Organization]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/orgs/{orgId} + +

+
+ +
+ +

Retrieve an organization given a specified UUID or username.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of created Organization.
    • +
    • Schema: [Organization]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/orgs/{orgId}/activate + +

+
+ +
+ +

Activate an organization from a link provIded in an email notification.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + token (string)
    + Activation token. (Specified in query). +
  • +
  • + confirm_email (boolean)
    + Send confirmation email or not. (Specified in query). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of complete messages.
    • +
    • Schema: [Action]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/orgs/{orgId}/apps + +

+
+ +
+ +

Retrieve the applications in an organization through providing both Id of application and organization.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of retrieved application data.
    • +
    • Schema: [AppData]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/orgs/{orgId}/apps/{appId}/credentials + +

+
+ +
+ +

Retrieve the client Id and client secret credentials for an application in an organization.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of retrieved credentials info.
    • +
    • Schema: [Credential]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /management/orgs/{orgId}/apps/{appId}/credentials + +

+
+ +
+ +

Generate the client Id and client secret credentials for an application in an organization.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of generated credentials info.
    • +
    • Schema: [Credential]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/orgs/{orgId}/credentials + +

+
+ +
+ +

Retrieve the credentials for an organization client.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of Credential
    • +
    • Schema: [Credential]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /management/orgs/{orgId}/credentials + +

+
+ +
+ +

Generate whole new credentials for an organization client.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of Credential
    • +
    • Schema: [Credential]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/orgs/{orgId}/feed + +

+
+ +
+ +

Retrieve an organization's activity feed.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of the organization's ActivityFeed.
    • +
    • Schema: [ActivityFeed]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/orgs/{orgId}/reactivate + +

+
+ +
+ +

Reactivate an expired organization.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of complete messages.
    • +
    • Schema: [Action]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /management/users/{userId}/feed + +

+
+ +
+ +

Retrieve an admin user's activity feed.

+ +

Parameters

+ +
    +
  • + userId (string)
    + One of the user's identification which includes username, real name, email address or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of user's activity
    • +
    • Schema: [ActivityFeed]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +

Permissions-Roles

+ +
+ +
+

GET /{orgId}/{appId}/roles + +

+
+ +
+ +

Retrieve the roles in an application through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of retrieved role's info.
    • +
    • Schema: [Role]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /{orgId}/{appId}/roles + +

+
+ +
+ +

Create a new role through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + roleproperty ( AddRole)
    + The required properties of the role. (Specified in body). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of created role's info.
    • +
    • Schema: [Role]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

DELETE /{orgId}/{appId}/roles/{roleId}/permissions + +

+
+ +
+ +

Remove permissions from a role.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + roleId (string)
    + One of the role's identification which includes name or uuid. (Specified in path). +
  • +
  • + grant_url_pattern (string)
    + The query statement of the url pattern. (Specified in query). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of deleted permission's info.
    • +
    • Schema: [Permission]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

GET /{orgId}/{appId}/roles/{roleId}/users + +

+
+ +
+ +

Retrieve the users in a role through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + roleId (string)
    + One of the role's identification which includes name or uuid. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of retrieved user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

POST /{orgId}/{appId}/roles/{roleId}/users/{userId} + +

+
+ +
+ +

Add a user to a role through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + roleId (string)
    + One of the role's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-3 (string)
    + One of the user's identification which includes username or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of added user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

DELETE /{orgId}/{appId}/roles/{roleId}/users/{userId} + +

+
+ +
+ +

Remove a user from a role through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + roleId (string)
    + One of the role's identification which includes name or uuid. (Specified in path). +
  • +
  • + userId-3 (string)
    + One of the user's identification which includes username or UUID. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of deleted user's info.
    • +
    • Schema: [User]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +
+ +
+

DELETE /{orgId}/{appId}/roles/{rolename} + +

+
+ +
+ +

Remove a role through providing all the identifications.

+ +

Parameters

+ +
    +
  • + orgId (string)
    + One of the organization's identification which includes name or uuid. (Specified in path). +
  • +
  • + appId (string)
    + One of the application's identification which includes name or uuid. (Specified in path). +
  • +
  • + rolename (string)
    + The name of the role. (Specified in path). +
  • +
+ +

Responses

+ +
    +
  • + 200 +
      +
    • Description: An array of deleted role's info.
    • +
    • Schema: [Role]
    • +
    +
  • +
  • + default +
      +
    • Description: Unexpected error.
    • +
    • Schema: [Error]
    • +
    +
  • +
+ +
+ +
+ +

Default Entity Models

This section lists the properties for the following Usergrid Default Entities:

+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
access_tokenstringAccess-token that may be used on subsequent requests.false
expires_innumberTime (in milliseconds) until access-token expires.false
userrefUser object if login was done as a user.false
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
actionstringThe requested action.false
statusstringThe status of the requested action.false
tokenstringThe token required for getting an AdminUser.false
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
entitypropertyreffalse
categorystringThe category of the activity.false
metadatapropertyreffalse
objectpropertyreffalse
titlestringThe title of the activity.false
verbstringThe verb of the activity.false
completeMsgreffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
displaynamestringThe display of the name of the actor.false
objecttypestringThe type of the actor.false
objectuuIdstringThe UUID of the actor.false
entitytypestringThe entitytype of the actor.false
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
operationstringA comma-delimited set of HTTP methods (GET, PUT, POST, DELETE) that are allowed for the specified resource path.true
resource_pathstringThe path to the resources to be accessed.true
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
titlestringThe title of the role.true
role namestringThe name of the role.true
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
citystringfalse
statestringfalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
tester/sandboxstringThe UUID of tester/sandbox.false
tester/app1stringThe UUID of tester/app1.false
tester/app2stringThe UUID of tester/app2.false
completeMsgreffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + +
NameTypeDescriptionRequired
canceledbooleantrue
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
activitiesstringfalse
feedstringfalse
rolesstringfalse
usersstringfalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
displayNamestringtrue
uuidstringtrue
usernamestringtrue
imagereffalse
verbstringtrue
contentstringtrue
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
usernamestringtrue
emailstringfalse
namestringfalse
passwordstringfalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
tokenstringThe OAuth2 access token.true
namestringThe name of the application.true
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + +
NameTypeDescriptionRequired
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
propertystringThe property of the entity.false
valuestringThe relevant value of the property.false
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + +
NameTypeDescriptionRequired
timestampstringtrue
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
titlestringThe title of the group.true
pathstringThe path of the group.true
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
notifierreftrue
messagestringThe push notitfication message that will be delivered to the user.true
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + +
NameTypeDescriptionRequired
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
organizationstringtrue
usernamestringtrue
namestringtrue
emailstringtrue
passwordstringtrue
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + +
NameTypeDescriptionRequired
usernamestringtrue
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
client_IdstringThe Id of the client.false
client_secretstringThe secret of the client.false
completeMsgreffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuidstringUnique entity Id.false
typestringType of entity.false
namestringNotifier display name.false
metadatareffalse
completeMsgreffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuidstringThe UUID of the entity.false
typestringThe type of the entity.false
actorpropertyreffalse
metadatareffalse
namestringThe name of the entity.false
messagestringfalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
codeintegerfalse
messagestringfalse
fieldsobjectfalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
applicationNamestringThe application name of the event.false
entityreffalse
urlstringThe url of the event.false
applicationIdstringThe application UUID of the event.false
parametersstringThe parameters of the event.false
organizationstringThe title of the organization.false
completeMsgreffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuidstringThe UUID of the group.false
typestringThe type of the group.false
createdstringThe created Id for the group.false
modifiedstringThe modified Id for the group.false
pathstringThe path of the group.false
metadatareffalse
titlestringThe title of the group.false
completeMsgreffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
urlstringfalse
wIdthintegerfalse
emailstringfalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
grant_typestringGrant-type must be 'password' or 'client_credentials'.false
usernamestringUsername of user attempting login, required only if grant_type is 'password'.false
passwordstringPassword of user attempting login, required only if grant_type is 'password'.false
client_idstringClient-ID portion of credentials, required only if grant_type is 'client_credentials'.false
client_secretstringClient-Secret portion of credentials, required only if grant_type is 'client_credentials'.false
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
cursorstringThe cursor of the metadata.false
pathstringThe path of the metadata.false
setsreffalse
collectionsreffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuidstringUnique entity Id.false
typestringType of entity.false
payloadsstringThe push notifications to be delivered.true
errorMessagestringError message returned by the notification service (APNs or GCM) if the notification fails entirely.false
scheduledbooleanwhether the notification is currently scheduled for delivery.false
statestringThe current delivery status of the notification 'FINISHED', 'SCHEDULED' or 'CANCELED'.false
metadatareffalse
completeMsgreffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuidstringUnique entity Id.false
typestringType of entity.false
namestringNotifier display name.false
providerstringPush notification provider 'apple' or 'google'.true
environmentstringThe environment that corresponds to your app 'development' or 'production'.true
metadatareffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
displaynamestringThe display of the name of the object.false
objecttypestringThe type of the object.false
objectuuIdstringThe UUID of the object.false
entitytypestringThe entitytype of the object.false
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
applicationIdstringThe application Id of the owner.false
usernamestringThe username of the owner.false
namestringThe name of the owner.false
emailstringThe email of the owner.false
activatedbooleanIndicate whether the account is activated or not.false
disabledbooleanIndicate whether the account is disabled or not.false
uuidstringThe UUID of the owner.false
adminUserbooleanIndicate whether the use is a adminUser or not.false
displayEmailstringThe display of the email of the owner.false
htmldisplayEmailstringThe HTML display of the email of the owner.false
orgnamestringThe name of the organization.false
orguuIdstringThe UUID of the organization.false
applicationdatareffalse
completeMsgreffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
applicationNamestringThe name of the application of the permission.false
entityreffalse
urlstringThe url of the permission.false
applicationIdstringThe UUID of the application.false
parametersstringThe parameters of the permission.false
organizationstringThe organization of the permission.false
permissiondatareffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
uuidstringUnique entity Id.false
typestringType of entity.false
payloadsstringThe push notifications to be delivered.false
errorMessagestringError message returned by the notification service (APNs or GCM) if the notification fails entirely.false
errorCodestringError code returned by the notification service.false
sentnumberUTC timestamp in milliseconds for when the notification was sent.false
metadatareffalse
completeMsgreffalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
passwordstringtrue
newpasswordstringtrue
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
recaptcha_responsestringParameters and value for the Captcha challenge.true
recaptcha_challengestringThe admin user's response to the Captcha challenge.true
emailstringtrue
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
applicationNamestringThe application name of the event.false
entityreffalse
urlstringThe url of the event.false
applicationIdstringThe application UUID of the event.false
parametersstringThe parameters of the event.false
organizationstringThe title of the organization.false
completeMsgreffalse
pathstringThe path of the role.false
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + +
NameTypeDescriptionRequired
timestampstringUTC timestamp in milliseconds of when schedule notifications.true
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + +
NameTypeDescriptionRequired
timestampstringUTC timestamp in milliseconds of when set expirations.true
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
rolenamesstringfalse
permissionsstringfalse
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +

Properties

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
applicationIdstringThe application Id of a user.false
usernamestringThe username of a user.false
namestringThe name of a user.false
emailstringThe email of a user.false
activatedbooleanIndicate whether the account is activated or not.false
disabledbooleanIndicate whether the account is disabled or not.false
uuidstringThe UUID of a user.false
adminUserbooleanIndicate whether the use is a adminUser or not.false
displayEmailstringThe display of the email of a user.false
htmldisplayEmailstringThe HTML display of the email of a user.false
organizationstringThe organization of the user.false
picturestringThe uri of the user's picture.false
uristringThe uri of the user.false
pathstringThe path of the user.false
completeMsgreffalse
+ +
+ +
+ +
+
+
+ + + + + + + + + diff --git a/content/docs/sdks/ios-new.html b/content/docs/sdks/ios-new.html new file mode 100644 index 0000000000..26c97e9ca6 --- /dev/null +++ b/content/docs/sdks/ios-new.html @@ -0,0 +1,1321 @@ + + + + + + + + + + + Usergrid iOS SDK — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Usergrid iOS SDK

+
+

Getting Started

+
+

Installing the SDK

+
+
+

Building from Source

+
+
+
+
+

Usergrid SDK Reference with Examples

+

The 66 topics listed below are each documented in the Usergrid +documentation and for each the docs provide an API reference and example +for each of these clients: curl, iOS, Android, JavaScript, Ruby and +Node.js.

+
+

Working with Collections

+
+

1. Creating collections

+

SDK Method

+
(ApigeeClientResponse *)apiRequest: (NSString *)url operation:(NSString *)op data:(NSString *)opData
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription
urlA fully-formed url in the following format: https://api.usergrid.com///
opThe HTTP method - in this case, ‘POST’
opDataNo data is being sent, so the value is nil
+

Example Request/Response

+

Request:

+
-(NSString*)createCollection {
+
+NSString *url = @"https://api.usergrid.com/your-org/your-app/items";
+NSString *op = @"POST";
+NSString *opData = nil;
+
+    //we recommend you call ApigeeClient from your AppDelegate.
+    //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+    //create an instance of AppDelegate
+    AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate];
+
+    //call createEntity to initiate the API call
+    ApigeeClientResponse *response = [appDelegate.dataClient apiRequest: url operation: op data: opData];
+
+@try {
+    //success
+}
+@catch (NSException * e) {
+    //fail
+}
+
+}
+
+
+

Response:

+
{
+  "action" : "post",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : { },
+  "path" : "/items",
+  "uri" : "http://api.usergrid.com/your-org/your-app/items",
+  "entities" : [ ],
+  "timestamp" : 1378857079220,
+  "duration" : 31,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+

2. Retrieving collections

+

SDK Method

+
(ApigeeCollection*)getCollection:(NSString*)type
+
+
+

Parameters

+ ++++ + + + + + + + + + + +
ParameterDescription
typeThe entity type associated with the collection to be retrieved
+

Example Request/Response

+

Request:

+
-(NSString*)getCollection {
+
+    //specify the entity type that corresponds to the collection to be retrieved
+    NSString *type = @"item";
+
+    //we recommend you call ApigeeClient from your AppDelegate.
+    //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+
+    //create an instance of AppDelegate
+    AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate];
+
+    //Call getCollection: to initiate the API GET request
+    ApigeeCollection *collection = [appDelegate.dataClient getCollection:@"book"];
+}
+
+
+

Response:

+
{
+      "action" : "get",
+      "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+      "params" : { },
+      "path" : "/items",
+      "uri" : "http://api.usergrid.com/your-org/your-app/items",
+      "entities" : [ {
+            "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4",
+            "type" : "item",
+            "name" : "milk",
+            "created" : 1378405020796,
+            "modified" : 1378405020796,
+            "metadata" : {
+                  "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4"
+            },
+            "name" : "milk",
+            "price" : "3.25"
+      }, {
+        "uuid" : "1a9356ba-1682-11e3-a72a-81581bbaf055",
+        "type" : "item",
+        "name" : "bread",
+        "created" : 1378423379867,
+        "modified" : 1378423379867,
+        "metadata" : {
+              "path" : "/items/1a9356ba-1682-11e3-a72a-81581bbaf055"
+        },
+        "name" : "bread",
+        "price" : "2.50"
+      } ],
+      "timestamp" : 1378426821261,
+      "duration" : 35,
+      "organization" : "your-org",
+      "applicationName" : "your-app",
+      "count" : 2
+}
+
+
+
+
+

3. Updating collections

+

SDK Method (ApigeeClientResponse *)apiRequest: (NSString *)url +operation:(NSString *)op data:(NSString *)opData Properties Parameter +Description url A fully-formed request url in the following format: +https://api.usergrid.com////?ql= Note that you must include an empty +‘?ql=’ query string at the end of the URL

+

op The HTTP method - in this case, ‘PUT’ opData A JSON-formatted string +that contains the entity properties to be updated Example +Request/Response Show Code Request: -(NSString*)updateCollection {

+
NSString *url = @"https://api.usergrid.com/your-org/your-app/items/?ql";
+NSString *op = @"PUT";
+NSString *opData = @"{\"availability\":\"in-stock\"}"; //we escape the quotes
+
+//we recommend you call ApigeeClient from your AppDelegate.
+//for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+//create an instance of AppDelegate
+AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
+
+//call apiRequest to initiate the API call
+ApigeeClientResponse *response = [appDelegate.dataClient apiRequest: url operation: op data: opData];
+
+@try {
+    //success
+}
+@catch (NSException * e) {
+    //fail
+}
+
+
+

}

+

Response: { “action” : “put”, “application” : +“f34f4222-a166-11e2-a7f7-02e81adcf3d0”, “params” : { “ql” : [ “” ] }, +“path” : “/items”, “uri” : +“http://api.usergrid.com/your-org/your-app/items”, “entities” : [ { +“uuid” : “31847b9a-1a62-11e3-be04-8d05e96f700d”, “type” : “item”, “name” +: “milk”, “price” : “3.25”, “availability” : “in-stock” “created” : +1378849479113, “modified” : 1378849567301, “name” : “milk”, }, { “uuid” +: “3192ac6a-1a62-11e3-a24f-496ca1d42ce7”, “type” : “item”, “name” : +“bread”, “price” : “4.00”, “availability” : “in-stock” “created” : +1378849479206, “modified” : 1378849567351, “name” : “bread”, } ], +“timestamp” : 1378849567280, “duration” : 207, “organization” : +“your-org”, “applicationName” : “your-app” }

+
+
+

4. Deleting collections

+

SDK Method (ApigeeClientResponse *)apiRequest: (NSString *)url +operation:(NSString *)op data:(NSString *)opData Properties Parameter +Description url A fully-formed url in the following format: +https://api.usergrid.com////?ql= Note that you must include an empty +‘?ql=’ query string at the end of the URL

+

op The HTTP method - in this case, ‘DELETE’ opData No data is being +sent, so the value is nil Example Request/Response The following example +will delete the first 5 entities in a collection.

+

Show Code Request: -(NSString*)deleteCollection {

+
NSString *url = @"https://api.usergrid.com/your-org/your-app/items/?ql='limit=5'";
+NSString *op = @"DELETE";
+NSString *opData = nil;
+
+//we recommend you call ApigeeClient from your AppDelegate.
+//for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+//create an instance of AppDelegate
+AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
+
+//call createEntity to initiate the API call
+ApigeeClientResponse *response = [appDelegate.dataClient apiRequest: url operation: op data: opData];
+
+@try {
+    //success
+}
+@catch (NSException * e) {
+    //fail
+}
+
+
+

}

+

Response: { “action” : “delete”, “application” : +“f34f4222-a166-11e2-a7f7-02e81adcf3d0”, “params” : { “ql” : [ “” ] }, +“path” : “/items”, “uri” : +“http://api.usergrid.com/your-org/your-app/items”, “entities” : [ { +“uuid” : “53fe3700-0abe-11e3-b1f7-1bd100b8059e”, “type” : “item”, “name” +: “milk”, “price” : “3.25”, “created” : 1377129832047, “modified” : +1377129832047, “metadata” : { “path” : +“/items/53fe3700-0abe-11e3-b1f7-1bd100b8059e” }, “name” : “milk” }, { +“uuid” : “5ae1fa7a-0abe-11e3-89ab-6be0003c809b”, “type” : “item”, “name” +: “bread”, “price” : “4.00”, “created” : 1377129843607, “modified” : +1377129843607, “metadata” : { “path” : +“/items/5ae1fa7a-0abe-11e3-89ab-6be0003c809b” }, “name” : “bread” } ], +“timestamp” : 1378848117272, “duration” : 12275, “organization” : +“your-org”, “applicationName” : “your-app” }

+
+
+
+

Working with Entities

+
+

5. Creating a custom entity

+

SDK Method (ApigeeClientResponse *)createEntity:(NSDictionary +*)newEntity Parameters Parameter Description newEntity NSDictionary +object that contains the entity properties Example Request/Response Show +Code Request: -(NSString*)newEntity {

+
//create an entity object
+NSMutableDictionary *entity = [[NSMutableDictionary alloc] init ];
+
+//Set entity properties
+[entity setObject:@"item" forKey:@"type"]; //Required. New entity type to create
+[entity setObject:@"milk" forKey:@"name"];
+[entity setObject:@"3.25" forKey:@"price"];
+
+//we recommend you call ApigeeClient from your AppDelegate.
+//for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+//create an instance of AppDelegate
+AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate];
+
+//call createEntity to initiate the API call
+ApigeeClientResponse *response = [appDelegate.dataClient createEntity:entity];
+
+@try {
+    //success
+}
+@catch (NSException * e) {
+    //fail
+}
+
+
+

}

+

Response: { “action” : “post”, “application” : +“4a1edb70-d7a8-11e2-9ce3-f315e5aa568a”, “params” : { }, “path” : +“/items”, “uri” : “http://api.usergrid.com/my-org/my-app/items”, +“entities” : [ { “uuid” : “83e9b7ea-e8f5-11e2-84df-e94123890c7a”, “type” +: “item”, “name” : “milk”, “created” : 1373415195230, “modified” : +1373415195230, “metadata” : {

+
            "path" : "/items/83e9b7ea-e8f5-11e2-84df-e94123890c7a"
+        },
+        "name" : "milk",
+        "price" : "3.25"
+    } ],
+    "timestamp" : 1373415195225,
+    "duration" : 635,
+    "organization" : "my-org",
+    "applicationName" : "my-app"
+}
+
+
+
+
+

6. Creating multiple custom entities

+

Request Syntax curl -X POST https://api.usergrid.com//// -d ‘[{}, {}, +...]’ Parameters Parameter Description org Organization UUID or name app +Application UUID or name entity_type Custom entity type to create. API +Services will create a corresponding collection if one does not already +exist. To add an entity to an existing collections, use the collection +name or colleciton UUID in place of the entity type. entity +Comma-separated list of entity objects to create. Each object should be +formatted as a comma-separated list of entity properties, formatted as +key-value pairs in the format : Example Request/Response Show Code +Request: curl -X POST “https://api.usergrid.com/your-org/your-app/item” +-d ‘[{“name”:”milk”, “price”:”3.25”}, {“name”:”bread”, “price”:”2.50”}]’ +Response: { “action” : “post”, “application” : +“f34f4222-a166-11e2-a7f7-02e9sjwsf3d0”, “params” : { }, “path” : +“/items”, “uri” : “http://api.usergrid.com/your-org/your-app/items”, +“entities” : [ { “uuid” : “f3a8061a-ef0b-11e2-9e92-5f4a65c16193”, “type” +: “item”, “name” : “milk”, “price” : “3.25”, “created” : 1374084538609, +“modified” : 1374084538609, “metadata” : { “path” : +“/multis/f3a8061a-ef0b-11e2-9e92-5f4a65c16193” }, “name” : “milk” }, { +“uuid” : “f3be262a-ef0b-11e2-a51b-6715d5ef47a6”, “type” : “item”, “name” +: “bread”, “price” : “2.50”, “created” : 1374084538754, “modified” : +1374084538754, “metadata” : { “path” : +“/items/f3be262a-ef0b-11e2-a51b-6715d5ef47a6” }, “name” : “bread” } ], +“timestamp” : 1374084538584, “duration” : 388, “organization” : +“your-org”, “applicationName” : “your-app” }

+
+
+

7. Creating an entity with sub-properties

+

SDK Method (ApigeeClientResponse *)createEntity:(NSDictionary +*)newEntity Parameters Parameter Description newEntity +NSMutableDictionary object that contains the entity properties Example +Request/Response Show Code Request: -(NSString*)newEntity {

+
//Initialize an object for the new entity to be created
+NSMutableDictionary *entity = [ [NSMutableDictionary alloc] init ];
+
+//Initialize an object for each nested variety object
+NSMutableDictionary *variety_1 = [ [NSMutableDictionary alloc] init ];
+NSMutableDictionary *variety_2 = [ [NSMutableDictionary alloc] init ];
+NSMutableDictionary *variety_3 = [ [NSMutableDictionary alloc] init ];
+
+//Initialize an array to hold the nested variety objects
+NSMutableArray *variety_list = [ [NSMutableArray alloc] init];
+
+[variety_1 setObject:@"1%" forKey:@"name"];
+[variety_1 setObject:@"3.25" forKey:@"price"];
+[variety_1 setObject:@"0393847575533445" forKey:@"sku"];
+
+[variety_2 setObject:@"whole" forKey:@"name"];
+[variety_2 setObject:@"3.85" forKey:@"price"];
+[variety_2 setObject:@"0393394956788445" forKey:@"sku"];
+
+[variety_3 setObject:@"skim" forKey:@"name"];
+[variety_3 setObject:@"4.00" forKey:@"price"];
+[variety_3 setObject:@"0390299933488445" forKey:@"sku"];
+
+//Add the variety objects to the array
+[variety_list addObject:variety_1];
+[variety_list addObject:variety_2];
+[variety_list addObject:variety_3];
+
+//Set the item entity properties
+[entity setObject:@"item" forKey:@"type"]; //Required. New entity type to create
+[entity setObject:@"milk" forKey:@"name"];
+
+//Set the variety_list array as the value of the 'varieties' property
+[entity setObject:variety_list forKey:@"varieties"];
+
+//we recommend you call ApigeeClient from your AppDelegate.
+//for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+//create an instance of AppDelegate
+AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate];
+
+//call createEntity to initiate the API call
+ApigeeClientResponse *response = [appDelegate.dataClient createEntity:entity];
+
+@try {
+    //success
+}
+@catch (NSException * e) {
+    //fail
+}
+
+
+

}

+

Response: { “action” : “post”, “application” : +“f34f4222-a166-11e2-a7f7-02e81adcf3d0”, “params” : { }, “path” : +“/items”, “uri” : “http://api.usergrid.com/your-org/your-app/items”, +“entities” : [ { “uuid” : “0d7cf92a-effb-11e2-917d-c5e707256e71”, “type” +: “item”, “name” : “milk”, “created” : 1374187231666, “modified” : +1374187231666, “metadata” : { “path” : +“/items/0d7cf92a-effb-11e2-917d-c5e707256e71” }, “name” : “milk”, +“varieties” : [ { “name” : “1%”, “price” : “3.25”, “SKU” : +“0393847575533445” }, { “name” : “whole”, “price” : “3.85”, “SKU” : +“0393394956788445” }, { “name” : “skim”, “price” : “4.00”, “SKU” : +“0390299933488445” } ] } ], “timestamp” : 1374187450826, “duration” : +50, “organization” : “your-org”, “applicationName” : “your-app” }

+
+
+

8. Retrieving an entity

+

SDK Method

+
(ApigeeClientResponse *)getEntities: (NSString *)endpoint query:(NSString *)query
+
+
+

Properties

+ ++++ + + + + + + + + + + + + + +
ParameterDescription
endpointThe collection and entity identifier of the entity to be retrieved.
queryAn optional query string. Requests for a specific entity should set the value to nil
+

Endpoint exported in the following format: /

+

Example Request/Response

+

Request:

+
-(NSString*)getEntity {
+
+    //specify the entity collection and UUID or name to be retrieved
+    NSString *endpoint = @"items/b3aad0a4-f322-11e2-a9c1-999e12039f87";
+
+    NSString *query = nil;
+
+    //we recommend you call ApigeeClient from your AppDelegate.
+    //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+    //create an instance of AppDelegate
+    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
+
+    //call getEntities to initiate the API call
+    ApigeeClientResponse *response = [appDelegate.dataClient getEntities:endpoint queryString:query];
+
+    @try {
+        //success
+    }
+
+    @catch (NSException * e) {
+        //fail
+    }
+
+}
+
+
+

Response:

+
{
+    "action" : "get",
+    "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+    "params" : { },
+    "path" : "/items",
+    "uri" : "http://api.usergrid.com/amuramoto/sandbox/items",
+    "entities" : [ {
+        "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4",
+        "type" : "item",
+        "name" : "milk",
+        "created" : 1378405020796,
+        "modified" : 1378405020796,
+        "metadata" : {
+              "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4"
+        },
+        "name" : "milk",
+        "price" : "3.25"
+    } ],
+    "timestamp" : 1378405025763,
+    "duration" : 31,
+    "organization" : "amuramoto",
+    "applicationName" : "sandbox"
+}
+
+
+
+
+

9. Retrieving multiple entities

+

SDK Method

+
(ApigeeClientResponse *)getEntities: (NSString *)type queryString:(NSString *)queryString
+
+
+

Properties

+ ++++ + + + + + + + + + + + + + +
ParameterDescription
typeThe entity type being retrieved
queryStringA query string of entity properties to be matched for the entities to be retrieved.
+

Query string is expected in the following format: = OR = OR ...

+

Example Request/Response

+

Request:

+
-(NSString*)getEntity {
+
+//specify the entity type to be retrieved
+NSString *type = @"item";
+
+//specify the uuid of the entity to be retrieved in a query string
+NSString *query = @"uuid = b3aad0a4-f322-11e2-a9c1-999e12039f87 or name = 'bread'";
+
+    //we recommend you call ApigeeClient from your AppDelegate.
+    //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+    //create an instance of AppDelegate
+    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
+
+    //call createEntity to initiate the API call
+    ApigeeClientResponse *response = [appDelegate.dataClient getEntities:type queryString:query];
+
+@try {
+    //success
+}
+@catch (NSException * e) {
+    //fail
+}
+
+}
+
+
+

Response:

+
{
+      "action" : "get",
+      "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+      "params" : {
+            "ql" : [ "name='milk' OR UUID=1a9356ba-1682-11e3-a72a-81581bbaf055" ]
+      },
+      "path" : "/items",
+      "uri" : "http://api.usergrid.com/your-org/your-app/items",
+      "entities" : [ {
+            "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4",
+            "type" : "item",
+            "name" : "milk",
+            "created" : 1378405020796,
+            "modified" : 1378405020796,
+            "metadata" : {
+                  "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4"
+        },
+            "name" : "milk",
+            "price" : "3.25"
+      }, {
+        "uuid" : "1a9356ba-1682-11e3-a72a-81581bbaf055",
+        "type" : "item",
+        "name" : "bread",
+        "created" : 1378423379867,
+        "modified" : 1378423379867,
+        "metadata" : {
+              "path" : "/items/1a9356ba-1682-11e3-a72a-81581bbaf055"
+        },
+            "name" : "bread",
+            "price" : "2.50"
+      } ],
+      "timestamp" : 1378423793729,
+      "duration" : 63,
+      "organization" : "your-org",
+      "applicationName" : "your-app",
+      "count" : 2
+}
+
+
+
+
+

10. Updating an entity

+

SDK Method

+
(ApigeeClientResponse *)updateEntity: (NSString *)entityID entity:(NSDictionary *)updatedEntity
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + +
ParameterDescription
entityIDUUID of the entity to be updated
updatedEntityNSMutableDictionary containing the properties to be updated
+

Example Request/Response

+

Request:

+
-(NSString*)updateEntity {
+
+    //UUID of the entity to be updated
+    NSString *entityID = @"f42752aa-08fe-11e3-8268-5bd5fa5f701f";
+
+    //Create an entity object
+    NSMutableDictionary *updatedEntity = [ [NSMutableDictionary alloc] init ];
+
+    //Set entity properties to be updated
+    [updatedEntity setObject:@"item" forKey:@"type"]; //Required - entity type
+    [updatedEntity setObject:@"in-stock" forKey:@"availability"];
+    [updatedEntity setObject:@"4.00" forKey:@"price"];
+
+    //we recommend you call ApigeeClient from your AppDelegate.
+    //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+    //create an instance of AppDelegate
+    AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate];
+
+    //call updateEntity to initiate the API call
+    ApigeeClientResponse *response = [appDelegate.dataClient updateEntity:entityID entity:updatedEntity];
+
+    @try {
+
+       //success
+
+    }
+    @catch (NSException * e) {
+        //fail
+    }
+
+}
+
+
+

Response:

+
{
+  "action" : "put",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : { },
+  "path" : "/items",
+  "uri" : "http://api.usergrid.com/your-org/your-app/items",
+  "entities" : [ {
+    "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4",
+    "type" : "item",
+    "name" : "milk",
+    "created" : 1378405020796,
+    "modified" : 1378505705077,
+    "availability" : "in-stock",
+    "metadata" : {
+      "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4"
+    },
+    "name" : "milk",
+    "price" : "4.00"
+  } ],
+  "timestamp" : 1378505705050,
+  "duration" : 87,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+

11. Updating a sub-property

+

SDK Method

+
(ApigeeClientResponse *)updateEntity: (NSString *)entityID entity:(NSDictionary *)updatedEntity
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + +
ParameterDescription
entityIDUUID of the entity to be updated
updatedEntityEntity object containing the properties to be updated
+

Example Request/Response

+

Request:

+
-(NSString*)updateEntity {
+
+    //UUID of the entity to be updated
+    NSString *entityID = @"f42752aa-08fe-11e3-8268-5bd5fa5f701f";
+
+    //Define our two sub-properties to include in the update
+    NSMutableDictionary *subproperty1 = [ [NSMutableDictionary alloc] init];
+    NSMutableDictionary *subproperty2 = [ [NSMutableDictionary alloc] init];
+    [subproperty1 setObject:@"1%" forKey:@"name"];
+    [subproperty1 setObject:@"3.25" forKey:@"price"];
+    [subproperty2 setObject:@"whole" forKey:@"name"];
+    [subproperty2 setObject:@"4.00" forKey:@"price"];
+
+    //Put our sub-properties into an NSArray
+    NSArray *subproperties = [ [NSArray alloc] initWithObjects:props1,props2, nil];
+
+    //Create an NSMutableDictionary to hold our updates
+    NSMutableDictionary *updatedEntity = [ [NSMutableDictionary alloc] init ];
+
+    //Set the properties to be updated
+    [updatedEntity setObject:@"item" forKey:@"type"]; //Required - entity type
+    [updatedEntity setObject:props forKey:@"varieties"];
+
+    //we recommend you call ApigeeClient from your AppDelegate.
+    //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+    //create an instance of AppDelegate
+    AppDelegate *appDelegate = (AppDelegate *)[ [UIApplication sharedApplication] delegate];
+
+    //call createEntity to initiate the API call
+    ApigeeClientResponse *response = [appDelegate.dataClient updateEntity:entityID entity:updatedEntity];
+
+    @try {
+
+       //success
+
+    }
+    @catch (NSException * e) {
+        //fail
+    }
+
+}
+
+
+

Response:

+
{
+  "action" : "put",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : { },
+  "path" : "/items",
+  "uri" : "http://api.usergrid.com/your-org/your-app/items",
+  "entities" : [ {
+    "uuid" : "5bb76bca-1657-11e3-903f-9ff6c621a7a4",
+    "type" : "item",
+    "name" : "milk",
+    "created" : 1378405020796,
+    "modified" : 1378761459069,
+    "availability" : "in-stock",
+    "metadata" : {
+      "path" : "/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4"
+    },
+    "name" : "milk",
+    "uri" : "http://api.usergrid.com/your-org/your-app/items/5bb76bca-1657-11e3-903f-9ff6c621a7a4",
+    "varieties" : [ {
+      "name" : "1%",
+      "price" : "3.25"
+    }, {
+      "name" : "whole",
+      "price" : "4.00"
+    } ]
+  } ],
+  "timestamp" : 1378761459047,
+  "duration" : 62,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+

12. Deleting data entities

+

SDK Method

+
(ApigeeClientResponse *)removeEntity: (NSString *)type entityID:(NSString *)entityID
+
+
+

Properties

+ ++++ + + + + + + + + + + + + + +
ParameterDescription
typeThe entity type being deleted
entityIDThe UUID or name of the entity to be removed
+

Example Request/Response

+

Request:

+
-(NSString*)deleteEntity {
+
+    //specify the entity type to be deleted
+    NSString *type = @"item";
+
+    //specify the uuid or name of the entity to be deleted
+    NSString *entityId = @"milk";
+
+    //we recommend you call ApigeeClient from your AppDelegate.
+    //for more information see the iOS SDK install guide: http://apigee.com/docs/app-services/content/installing-apigee-sdk-ios
+    //create an instance of AppDelegate
+    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
+
+    //call removeEntity to initiate the API call
+    ApigeeClientResponse *response = [appDelegate.dataClient removeEntity:type entityID:entityId];
+
+    @try {
+        //success
+    }
+    @catch (NSException * e) {
+        //fail
+    }
+}
+
+
+

Response:

+
{
+  "action" : "delete",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : { },
+  "path" : "/items",
+  "uri" : "http://api.usergrid.com/your-org/your-app/items",
+  "entities" : [ {
+    "uuid" : "328fe64a-19a0-11e3-8a2a-ebc6f49d1fc4",
+    "type" : "item",
+    "name" : "milk",
+    "created" : 1378766158500,
+    "modified" : 1378766158500,
+    "metadata" : {
+      "path" : "/items/328fe64a-19a0-11e3-8a2a-ebc6f49d1fc4"
+    },
+    "name" : "milk",
+    "price" : "3.25"
+  } ],
+  "timestamp" : 1378766172016,
+  "duration" : 324,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+
+

Data Queries

+
+

13. Querying your data

+
+
+
+

Entity Connections

+
+

14. Connecting users other data

+
+
+

15. Retrieving user connection data

+
+
+

16. Disconnecting entities

+
+
+
+

Permissions & Roles

+
+

17. Assigning permissions

+
+
+

18. Removing permissions

+
+
+

19. Assigning permissions

+
+
+

20. Removing permissions

+
+
+

21. Creating roles

+
+
+

22. Assigning roles

+
+
+

23. Removing roles

+
+
+
+

Authentication

+
+

24. Application user authentication (user login)

+
+
+

25. Application client authentication

+
+
+

26. Admin user authentication

+
+
+

27. Organization client authentication

+
+
+

28. Revoking tokens (user logout)

+
+
+
+
+

Working with Users & Groups

+
+

Activities & Feeds

+
+

37. Posting a user activity

+
+
+

38. Posting an activity to a group

+
+
+

39. Creating an activity for a user’s followers in a group

+
+
+

40. Retrieving a user’s activity feed

+
+
+

41. Retrieving a group’s activity feed

+
+
+
+

Events & Counters

+
+

42. Creating & incrementing counters

+
+
+

43. Retrieving counters

+
+
+

44. Retrieving counters by time interval

+
+
+
+

Managing Orgs & Apps

+
+

46. Creating an organization

+
+
+

47. Getting an organization

+
+
+

48. Activating an organization

+
+
+

49. Reactivating an organization

+
+
+

50. Generating organization client credentials

+
+
+

51. Retrieving organization client credentials

+
+
+

52. Getting an organization’s activity feed

+
+
+

53. Getting the applications in an organization

+
+
+

54. Getting the admin users in an organization

+
+
+

55. Removing an admin user from an organization

+
+
+

56. Creating an organization application

+
+
+

57. Generating application credentials

+
+
+

58. Getting application credentials

+
+
+
+

Managing Admin Users

+
+

59. Creating an admin user

+
+
+

60. Updating an admin user

+
+
+

61. Getting an admin user

+
+
+

62. Setting an admin user’s password

+
+
+

63. Resetting an admin user’s password

+
+
+

64. Activating an admin user

+
+
+

65. Reactivating an admin user

+
+
+

66. Getting an admin user’s activity feed

+
+
+
+ + +
+
+
+ + +
+ +
+

+ © Copyright 2013-2015, Apache Usergrid. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/sdks/ios.html b/content/docs/sdks/ios.html new file mode 100644 index 0000000000..e77c1c5abd --- /dev/null +++ b/content/docs/sdks/ios.html @@ -0,0 +1,280 @@ + + + + + + + + + + + iOS SDK — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

iOS SDK

+
+ + +
+
+
+ + +
+ +
+

+ © Copyright 2013-2015, Apache Usergrid. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/sdks/java.html b/content/docs/sdks/java.html new file mode 100644 index 0000000000..e94bcc00ed --- /dev/null +++ b/content/docs/sdks/java.html @@ -0,0 +1,280 @@ + + + + + + + + + + + Java SDK — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Java SDK

+
+ + +
+
+
+ + +
+ +
+

+ © Copyright 2013-2015, Apache Usergrid. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/sdks/javascript.html b/content/docs/sdks/javascript.html new file mode 100644 index 0000000000..bf4e87ec5f --- /dev/null +++ b/content/docs/sdks/javascript.html @@ -0,0 +1,280 @@ + + + + + + + + + + + JavaScript/HTML5 SDK — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

JavaScript/HTML5 SDK

+
+ + +
+
+
+ + +
+ +
+

+ © Copyright 2013-2015, Apache Usergrid. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/sdks/sdk-outline.html b/content/docs/sdks/sdk-outline.html new file mode 100644 index 0000000000..237ee38501 --- /dev/null +++ b/content/docs/sdks/sdk-outline.html @@ -0,0 +1,514 @@ + + + + + + + + + + + Usergrid SDK Documentation outline — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Usergrid SDK Documentation outline

+
+

Getting Started

+
+

Installing the SDK

+
+
+

Building from Source

+
+
+
+
+

Usergrid SDK Reference with Examples

+

The 66 topics listed below are each documented in the Usergrid +documentation and for each the docs provide an API reference and example +for each of these clients: curl, iOS, Android, JavaScript, Ruby and +Node.js.

+
+

Working with Collections

+
+

1. Creating collections

+
+
+

2. Retrieving collections

+
+
+

3. Updating collections

+
+
+

4. Deleting collections

+
+
+
+

Working with Entities

+
+

5. Creating a custom entity

+
+
+

6. Creating multiple custom entities

+
+
+

7. Creating an entity with sub-properties

+
+
+

8. Retrieving an entity

+
+
+

9. Retrieving multiple entities

+
+
+

10. Updating an entity

+
+
+

11. Updating a sub-property

+
+
+

12. Deleting data entities

+
+
+
+

Data Queries

+
+

13. Querying your data

+
+
+
+

Entity Connections

+
+

14. Connecting users other data

+
+
+

15. Retrieving user connection data

+
+
+

16. Disconnecting entities

+
+
+
+

Permissions & Roles

+
+

17. Assigning permissions

+
+
+

18. Removing permissions

+
+
+

19. Assigning permissions

+
+
+

20. Removing permissions

+
+
+

21. Creating roles

+
+
+

22. Assigning roles

+
+
+

23. Removing roles

+
+
+
+

Authentication

+
+

24. Application user authentication (user login)

+
+
+

25. Application client authentication

+
+
+

26. Admin user authentication

+
+
+

27. Organization client authentication

+
+
+

28. Revoking tokens (user logout)

+
+
+
+
+

Working with Users & Groups

+
+

Activities & Feeds

+
+

37. Posting a user activity

+
+
+

38. Posting an activity to a group

+
+
+

39. Creating an activity for a user’s followers in a group

+
+
+

40. Retrieving a user’s activity feed

+
+
+

41. Retrieving a group’s activity feed

+
+
+
+

Events & Counters

+
+

42. Creating & incrementing counters

+
+
+

43. Retrieving counters

+
+
+

44. Retrieving counters by time interval

+
+
+
+

Managing Orgs & Apps

+
+

46. Creating an organization

+
+
+

47. Getting an organization

+
+
+

48. Activating an organization

+
+
+

49. Reactivating an organization

+
+
+

50. Generating organization client credentials

+
+
+

51. Retrieving organization client credentials

+
+
+

52. Getting an organization’s activity feed

+
+
+

53. Getting the applications in an organization

+
+
+

54. Getting the admin users in an organization

+
+
+

55. Removing an admin user from an organization

+
+
+

56. Creating an organization application

+
+
+

57. Generating application credentials

+
+
+

58. Getting application credentials

+
+
+
+

Managing Admin Users

+
+

59. Creating an admin user

+
+
+

60. Updating an admin user

+
+
+

61. Getting an admin user

+
+
+

62. Setting an admin user’s password

+
+
+

63. Resetting an admin user’s password

+
+
+

64. Activating an admin user

+
+
+

65. Reactivating an admin user

+
+
+

66. Getting an admin user’s activity feed

+
+
+
+ + +
+
+
+ + +
+ +
+

+ © Copyright 2013-2015, Apache Usergrid. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/sdks/tbd.html b/content/docs/sdks/tbd.html new file mode 100644 index 0000000000..4be546294a --- /dev/null +++ b/content/docs/sdks/tbd.html @@ -0,0 +1,305 @@ + + + + + + + + + + + COMING SOON... — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

COMING SOON...

+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/search.html b/content/docs/search.html new file mode 100644 index 0000000000..5ed42a9bca --- /dev/null +++ b/content/docs/search.html @@ -0,0 +1,307 @@ + + + + + + + + + + + Search — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+
    +
  • Docs »
  • + +
  • +
  • + +
  • +
+
+
+
+
+ + + + +
+ +
+ +
+
+
+ + +
+ +
+

+ © Copyright 2013-2015, Apache Usergrid. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/searchindex.js b/content/docs/searchindex.js new file mode 100644 index 0000000000..15d72a497a --- /dev/null +++ b/content/docs/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({envversion:46,filenames:["README","assets-and-files/file-storage-configuration","assets-and-files/folders","assets-and-files/legacy-asset-support","assets-and-files/retrieving-assets","assets-and-files/uploading-assets","counters-and-events/creating-and-incrementing-counters","counters-and-events/events-and-counters","counters-and-events/retrieving-counters","data-queries/advanced-query-usage","data-queries/operators-and-types","data-queries/query-parameters","data-queries/querying-your-data","data-storage/collections","data-storage/data-store-dbms","data-storage/entities","data-storage/optimizing-access","entity-connections/connecting-entities","entity-connections/disconnecting-entities","entity-connections/retrieving-entities","geolocation/geolocation","index","installation/deployment-guide","installation/ug1-deploy-to-tomcat","installation/ug1-launcher-quick-start","installation/ug2-deploy-to-tomcat","introduction/async-vs-sync","introduction/data-model","introduction/overview","introduction/usergrid-features","jersey2skeleton/README","orgs-and-apps/admin-user","orgs-and-apps/application","orgs-and-apps/managing","orgs-and-apps/organization","push-notifications/adding-push-support","push-notifications/creating-and-managing-notifications","push-notifications/creating-notifiers","push-notifications/getting-started","push-notifications/managing-users-and-devices","push-notifications/overview","push-notifications/registering","push-notifications/tbd","push-notifications/troubleshooting","push-notifications/tutorial","push-notifications/users-devices","reference/contribute-code","reference/presos-and-videos","rest-endpoints/api-docs","sdks/ios-new","sdks/sdk-outline","sdks/tbd","security-and-auth/app-security","security-and-auth/authenticating-api-requests","security-and-auth/authenticating-users-and-application-clients","security-and-auth/changing-token-time-live-ttl","security-and-auth/facebook-sign","security-and-auth/revoking-tokens-logout","security-and-auth/securing-your-app","security-and-auth/user-authentication-types","security-and-auth/using-permissions","security-and-auth/using-roles","user-management/activity","user-management/group","user-management/groups","user-management/messagee-example","user-management/user-connections","user-management/user-management","user-management/working-user-data","using-usergrid/creating-a-new-application","using-usergrid/creating-account","using-usergrid/using-a-sandbox-app","using-usergrid/using-the-api"],objects:{},objnames:{},objtypes:{},terms:{"005056c00008":68,"00767101f6b4f2cf5d02ed510dbcf0b4":63,"02e81ac5a17b":[2,10],"02e81adcf3d0":[5,6,8,13,15,18,19,49,60,61,62,63,72],"02e81ae236e9":63,"02e81ae61238":63,"02e81ae640dc":[2,62],"02e81ae66238":63,"02e81aeb2129":63,"02e81aeb26e9":63,"02e9sjwsf3d0":[15,49],"03ae956a":20,"0455fc92de2636fc7a176cc5d298bb78":63,"08fe":49,"0abe":[13,49],"0d7cf92a":[15,49],"0d7e":34,"0d7f":34,"0f1ff3650d20":[17,63,68],"10e":10,"10e10":10,"11apigeeapsdestination11":36,"11e0":[8,68],"11e1":[2,27,31,34,62,63,68,72],"11e2":[2,5,6,8,10,12,13,15,18,19,34,49,60,61,62,63,72],"11e3":[5,13,15,17,18,19,20,49,55,61,63,68,72],"1231380a0284":62,"12313b01d5c1":[2,27,62,72],"12313b06ae01":62,"12313b06d112":62,"12313b111c56":34,"12313b122c56":[31,34],"12313d027361":34,"12313d027471":34,"12313d14bde7":63,"12313d1520f1":62,"12313d1c4491":[2,31,34,62],"12313d1c44914":62,"12313d1c5591":34,"12313d288ee0":34,"12313d288ff0":34,"12313d331ae8":62,"12313f0204b":68,"12313f0204bb":[8,68],"12313f0204bb8":68,"12331b144c65":31,"12331d1c5591":[31,34],"12424d1c4491":31,"174785aa":17,"19a0":[15,49],"1a62":[13,49],"1a9356ba":[13,15,49],"1bd100b8059e":[13,49],"1c8f60e4":68,"1f3567aa":62,"1px":47,"1st":48,"20adr":68,"20c57d4f41cf51f2db44165eb058b3b2":12,"20employe":63,"20or":15,"20titl":63,"20uuid":15,"20where":[63,68],"22000a1c4e22":63,"22000a1c5a67":[63,68],"2440ca58":62,"2482a1c5":62,"249f":20,"2ac6":2,"2ac8":2,"2d00":62,"2d21":2,"2e1db7299b0a667ed80e674a0ef9d653":5,"2nd":48,"31847b9a":[13,49],"3192ac6a":[13,49],"327b527f":[31,34],"328b526e":31,"328fe64a":[15,49],"335b527f":[31,34],"33dd0563":[31,34],"3400ba10":[2,34,62],"348388de":61,"34e26bc9":62,"3500ba10":34,"37f3":62,"382d0991":61,"38dc":15,"3bee":39,"3c1e":61,"3d1a9356ba":15,"3rd":22,"410b213a":[5,61],"411c466c4f2c":12,"417f":[17,63,68],"4353136f":68,"438a1ca1":8,"477d":63,"48c92c73":34,"496ca1d42ce7":[13,49],"49ff":62,"4a1edb70":[15,49],"4d2664c8e0c3":63,"4f511f12a386":39,"5005a0fa":63,"503f17da":72,"50gb":1,"5111c463":62,"5373d7165c2d":55,"53fe3700":[13,49],"563f5d96":62,"58606d0a":[18,19],"58e8":[63,68],"595955dff9ee4a706de9d97b86c5f0636fe24b43":22,"5ae1fa7a":[13,49],"5bb76bca":[13,15,49],"5bcc47ca":[18,19],"5bd5fa5f701f":49,"5c0c1789":[2,27],"5de0bb69":34,"5f4a65c16193":[15,49],"5wugd":54,"61c9":62,"62de5d97":72,"62fd53c78ce7":60,"65c8":34,"6640a601":2,"6715d5ef47a6":[15,49],"67cb":63,"698b":63,"699740088e05":6,"6a42":62,"6b07e44495ef":61,"6be0003c809b":[13,49],"6c56ffda":17,"6fbc8157":63,"6ldstnesaaaaakhdvglhmmu86_eoyxsjjqqd1ipz":[31,68],"74bb":61,"74d2d7da":63,"78c54a82":68,"7a0a1cba":39,"7bf47435":2,"7fb8d891":63,"802f":63,"81581bbaf055":[13,15,49],"8272c9b0":12,"83ceb9965c26":63,"83de":63,"83e9b7ea":[15,49],"84a5":68,"84c0":62,"84df":[15,49],"87b9":34,"884d":68,"89ab":[13,49],"8a2a":[15,49],"8a4c":60,"8ae3":39,"8ae8a6ea":68,"8bde":[18,19],"8cef":12,"8d05e96f700d":[13,49],"8d5c":72,"8dd1801e534c":17,"8e0cd3866ee20746c99e9a9825f38ad8":2,"8ea8":17,"903f":[13,15,49],"90f823ba15655b8cc8e3b4d63377576f":63,"917d":[15,49],"924d":10,"92c3":2,"92e2":12,"9501cda1":2,"95c8":[31,34],"96f6":62,"98b9":34,"9953085ea376":[5,61],"999e12039f87":49,"99a7":55,"99fd":17,"9a18":39,"9c1b":63,"9ce3":[15,49],"9d3a":6,"9de5":61,"9e75":17,"9e92":[15,49],"9efc8ad529d8":61,"9f80":20,"9ff6c621a7a4":[13,15,49],"9ffc":62,"____usergrid":23,"__weak":36,"_set":22,"boolean":[10,34,45,48],"byte":36,"case":[9,16,23,26,35,38,43,45,48,49,62,64,66],"catch":49,"class":[1,22,25,31,36,39,54,57,68],"default":[1,10,11,12,13,14,15,20,21,22,23,25],"export":[22,41,44,49],"final":[39,41],"float":10,"function":[6,26,29,39,56,59,62,63,64,65,67],"import":[26,27,29,35,38,39,44,52,71,72],"long":[10,27,36,45,64],"new":[6,9,13,15,16,21,28,31,32,34,35,36,38,39,40,41,43,44,45,48,49,55,56,58,61,62,63,65,68],"null":[6,39,56],"public":[31,39,41,68],"return":[10,11,12,13,16,19,20,24,26,31,34,39,41,45,48,54,55,56,57,60,62,63],"short":[62,70],"static":[22,23,39,46],"throw":[35,43],"transient":25,"true":[10,12,18,19,22,23,24,25,31,34,36,39,48,56,61,63,68,72],"try":[24,31,35,36,43,49,52,56,60,70,71],"typeof":56,"var":[9,22,31,39,56],"void":[36,39],"while":[23,26,27,29,35,38,39,40,43,45,60,61,71],a065:62,a0dd:72,a0e5:[5,61],a0f7:62,a166:[5,6,8,13,15,18,19,49,60,61,63,72],a24f:[13,49],a407b1e7:[63,68],a51b:[15,49],a554b7fbd57a:72,a5c5:61,a668717b:63,a694:[18,19],a6e3:63,a71c:60,a72a:[13,15,49],a7e008061e10:[18,19],a7f7:[5,6,8,13,15,18,19,49,60,61,63,72],a9c1:49,abbrevi:[12,16,41,72],abil:[20,29,66,67,70],abl:[16,22,23,25,35,36,38,44,58,59,62,67,68,72],about:[0,10,16,21,23,29,31,33,34,35,36,38,39,40],abov:[5,6,10,19,22,23,24,25,35,38,39,44,61,62],abstractbatch:22,abstractcomposit:22,ac46:[63,68],accept:[4,37,39,46,54,60],access:[2,13,14,15,16,19,21,22,24,27,29,31,32,33,34,36,39,41,45],access_token:[24,48,53,54,55,56],accessid:1,accesstokenrespons:21,accesstokenttl:55,accomplish:[36,57],accord:54,account:[12,15,16,21,22,23,25,27,29,31,33,35,38,39,41,44,45,48,55,58,59,61],achiev:66,acquaint:62,acquir:21,across:[8,16,36],act:[12,62,65],action:[2,5,6,7,8,12,13,14,15,16,17,18,19,21,22,23,29,31,32,34,35,36,44],activ:[5,10,12,18,19,20,21,22,23,25,27],activit:31,activityfe:21,actor:[31,34,48,62],actual:[16,35,38,44],add:[1,9,14,15,16],add_invoc:22,addit:[8,16,21],addobject:49,address:[12,22,23,31,34,35,38,41,45,48,54,68,72],addrol:21,adjust:[11,61],admin:[21,22,23,24,25],admin_password:54,admin_usernam:54,admin_users_require_activ:[22,23,25],admin_users_require_confirm:[22,23,25],admingmail:31,administr:[23,24,27,29,32,34,45,54,58,59,61],adminus:[31,34,48],adomain:68,adopt:29,advantag:29,advertis:20,advis:58,ae1f:17,aec3:62,afad:62,affect:55,after:[6,10,24,26,35,36,38,39,44,54,56,58,61,65,72],again:[23,31,35,43],against:[18,25,32,53,54,58,60],aggreg:8,air:14,aizasyckxotbq7a9gojsslqzlod_yjefxxxxxxx:37,alert:[20,26,36,39,63,64],alerttext:36,alia:[61,68],all:[0,6,8],alloc:[36,39,49],allow:[7,10,12,20,22,23,25,27,29,34,36,39,41,44,45,56,59,60,61,62,63,64,66,67,68,72],allowajaxfilt:22,almost:67,alon:[35,38],along:[11,16,35,39,43],alreadi:[15,16,22,23,35,36,37,39,45,48,49,56,58,65,70],also:[1,2,6,7,8,11,13,15,16,22,24,25,27,29,31,32,34,35,36,37,38,39,44,45,48,54,56,57,58,60,62,63,64,65,66,68,69],alter:61,altern:[12,13,63,64],although:[13,15,31,36,62,63,68],alwai:[27,36],amazon:1,amazonaw:23,amount:[11,59,62],amuramoto:[5,15,49,55],analysi:29,analyt:70,analyz:[29,53,54,58,59],android:[21,26],androiddev:37,androidmanifest:44,anew:[35,43],angular:46,ani:[5,6,8,10,12,14,15,16,20,22,25,26,27,29,31,33,36,39,44,48,52,53,54,55,58,59,60,61,62,63,65,66,67,68],annot:30,announc:40,anonym:[45,62,68],anoth:[12,16,35,36,38,43,44,53,62,65,66,68,71],answer:68,ant:60,anuff:47,anyon:[59,62],anyth:23,anytim:62,anywher:11,apachecon:47,apidocgener:0,apige:[35,36,39,40,41,44,47,49,63,72],apigeeapsdestin:36,apigeeapspayload:36,apigeecli:[39,49],apigeeclientrespons:[36,39,49],apigeecollect:49,apigeedatacli:36,apigeedataclientcompletionhandl:36,apigeemobileconfig:55,apikei:[37,56],apirequest:49,apirespons:39,apiresponsecallback:39,apn:21,app1:48,app2:48,app:[2,4,5,6,7,8,12,13,14,15,16,17,18,19],app_id:[15,48,62,63,68],app_nam:[32,55,57],app_uuid:[14,16],appdata:21,appdeleg:[36,39,44,49],appear:[19,25,37,41,48,62,65,66],append:[8,9,13,16,20,22,36,53,56],appid:[48,56],appl:[21,29],appledev:44,applenotifi:37,appleopt:39,appli:[25,55,58,60,61,66,67,68,72],applic:[2,4,5,6,7,8,12,13,14,15,16,17,18,19,20,21,22,23,24,26],application_client_secret:54,application_clientid:54,application_info:34,applicationdata:48,applicationdidbecomeact:39,applicationid:[31,34,39,48],applicationnam:[2,5,6,8,12,13,14,15,16,17,18,19,48,49,55,60,61,62,63,68,72],appnam:[9,39,44,54,56],appropri:[27,36,37,39,45,56],approv:[22,23,25],appservic:39,aps_develop:41,apspayload:36,arbitrari:[66,72],architectur:[14,23],archiv:22,area:[31,36,41,52,68,70,71],aren:[14,16],arg:[1,32,34,62,63],argument:[1,39],arm:58,around:[0,16,22],arrai:[10,12,14,15,16,19,48,49,72],arthur:[17,18,19,66,67],articl:[12,13,15,53,61],asc:11,ascend:11,ask:[12,44],aspect:[7,29],asset1:2,asset:1,assets_id:2,assign:[6,21,27,29,45],assist:41,associ:[5,10,13,19,20,27,29,34,35,36,37,38,39,41,44,45,48,49,52,54,55,57,59,61,63,65,67,68,69,72],assum:[16,25,39,44,53],async:21,asynchron:21,atistophan:31,atom:15,atop:44,attach:[4,5],attack:[52,58],attempt:[34,48,53],attribut:14,audienc:21,audio:[5,29],auth:[23,25,37,41,45,56],authent:[13,15,21,24,28],author:[24,33,37,39,41,53,55,56,62,67],author_uuid:16,authorid:[14,16],authorimag:16,authornam:16,authoruuid:16,authrespons:56,auto:[22,23,25],automat:[5,6,13,15,25,27,29,30,48,54,56,57,60,61,62,66,69,70],avail:[13,15,20,24,29,35,37,39,49,54,65,67,70,72],avatar:[12,62,63,68,72],avoid:[16,65],awai:16,awar:[10,20],awssdks3binarystor:1,b0c6:63,b11217fc:6,b1f7:[13,49],b24e:6,b2bd:63,b2e4:15,b31d:55,b36a:[2,27],b379:[5,61],b3aad0a4:49,b3u68vghi6fmeekn9wlogtzz0a:32,b3u6aaabmqz:54,b3u6zuz5_u8i:32,b4c6:2,b690:63,b6dd:62,b77ec8addc0d:63,b90c:63,b93d:68,baa:[22,31,34,36,37,41,52],back:[14,16,24,29,39,46,65],backend:[12,21,22,27,36],backslash:36,bad:[34,54,59],badg:[36,39],banner:7,bar1234b:68,bar:[28,72],barnei:[63,66],base:[0,13,20,21,22,23,25,29,36,37,54,67],baseurl:[22,39],bash:22,batch:11,baz:72,bcc1:8,bcf7:[2,31,34,62],bcf8:[31,34],bd397ea1:60,be04:[13,49],be08a5f9:34,be09a5f9:34,bean:[1,22],bearer:[24,37,53],beca:34,becaus:[14,20,23,35,43,48,54,58,59,62,65,71],becom:[11,12,20,23,29,41,62,63,64],been:[6,16,35,36,39,43,44,48,53,56,57,58,62],bef8:[31,34],befor:[0,1,21,22,26,35,36,38,39,41,43],begin:[8,11,21,22,33],behalf:54,behav:65,behavior:29,behind:[45,56,70],belong:[24,27,36,45,62,64],below:[13,14,15,16,22,23,25,31,35,36,38,44,49,50,56,62,63,65,68],beneath:65,benefici:26,benefit:[14,23],besid:61,best:[11,12],better:[16,54,59],bewar:25,beyond:62,bike:10,bin:[22,25],binari:[22,29,53,54,58,59],binarystor:1,bit:14,blank:[41,61],block:26,blog:61,blue:39,board:65,boat:10,boavijt0oyrkjf:32,bodi:[6,16,31,32,34,36,48,55,62,63,68],book:[11,29,49],bool:39,bootstrap:[22,25],border:47,both:[6,14,17,25,26,27,36,39,46,48,59,67],bottom:10,bounc:16,bouncer:16,bounci:[14,16],box:[36,44,61,65,67,69,71],bracket:15,bread:[13,15,49],brief:[26,56],broad:[53,54,59],brows:[22,28],browser:[22,23,31,35,38,56],bucketnam:1,buildcurl:56,built:[16,22,23,44,46,62,72],bunch:22,bundl:[39,44],busi:20,button:[7,31,35,38,41,43,44,61,65,68,69,71],button_click:[6,8],c2v7n61dy90mcdg78xixprxfdq:34,c2v7wedxiutzwekwdyslct_lydfvmmn:34,c5e707256e71:[15,49],california:[31,63,64],call:8,callback:[26,39,56],campaign:29,can:[0,1,2,4,5,6,7,8,10,11,12,13,14,15,16,17,19,20,22,23,24,25,26,27,29,31,32,33,34,35,36,37,38,39],cancel:21,cannot:[13,15,26,27,30,59,72],capabl:58,captcha:[31,48,68],captur:[12,16,20,29],car:10,care:[38,40,41],carefulli:59,carri:[33,37,44],cassandra:[14,16,21],cassandra_cluster_nam:22,cassandra_host:22,cassandraavail:22,cassandrastatu:22,cassanrda:22,cast:47,castl:[14,16],cat:24,catalina:[22,25],catalog:29,categori:[14,31,34,48],caus:[0,15,48],caution:55,cautiou:[53,54,59],ccc:47,cd0c:[2,31,34,62],cd0d:[31,34],cd789b00:63,cd796d0a:63,cdf1ce04c1c0:12,cdn:29,cede5b7:34,cede5b8:34,cell:0,center:[20,35,38,44],central:[0,1],cer:41,certain:[15,16,27,36,57,67],certif:[21,35,37,38],certsigningrequest:41,cf3e981c:31,cf4d981c:[31,34],cf9b:8,cfed:[18,19],chain:6,challeng:[31,48,68,72],chang:[0,1,21,22,23,25,27,44,48,53],changelog:22,channel:56,channelurl:56,charact:[11,62,68],characterist:[38,39],charset:[31,68],check:[22,23,24,25,39,44,56,59,60,61,62,71],checkbox:61,checksum:[2,5],chicago:68,choic:44,choos:[16,36,37,41],chose:44,circl:[29,62],circumst:57,cite:15,citi:[11,31,68],clara:47,classpath:1,clean:[0,23,24,25,31],cli:23,click:[7,16,33,35,36,37,38,41,43,44,61,65,69,71],client:[9,11,13,14,15,16,21,22,23,25,26,29,31,32,33],client_credenti:[32,48,54],client_id:[32,34,48,53,54,56],client_secret:[32,34,48,53,54],climb:16,clone:[0,23,25],close:44,closer:16,cloud:[1,4,5,22,29,35,38,41,44],clue:23,cluster:[22,23,25],cluster_nam:[22,25],cn0wtdxxkxmqlgzvtmubcp20fulczq:54,code:[1,11,16,21,23,24,26,28,29,30,35,36,38,39,40,41,43,44],codesign:44,coffe:14,colleagu:62,colleciton:49,collect:[4,5,12],collection_nam:13,collectionid:48,color:[10,39],column:[14,16],com:[2,4,5,6,8,12,13,14,15,16,17,18,19,20,22,23,24,25,27,31,32,34,36,37,39,41,44,45,49,54,55,56,57,60,61,62,63,65,66,67,68,72],combin:[16,30,35,36,38,58,68],come:[21,22,23,25],comma:[12,22,36,49,56,60],comma_separated_list_of_permission_nam:56,command:[0,22,23,24,25,44,56,63,70],comment:[29,39,62],commit:0,committ:46,common:[12,58,62,68],commonli:61,commun:[22,38,40,65],compani:[33,34,65],compar:[12,38],comparison:[10,61],compil:[44,53,54,58,59],complet:[12,21,23,26,27,29],completedsuccessfulli:[36,39],completemsg:48,completionhandl:36,complex:[15,16,21,29],compliant:29,complic:23,compon:[27,28,29,46],compris:22,compromis:53,concept:[14,70],config:[22,25],confim:48,confirm:[22,23,25,31,34,35,43,48,65],confirm_email:[31,34,48],conflict:65,conform:10,conjunct:[29,67],connect:[0,2,5,12,16],connected_collect:[17,18],connected_ent:[17,18],connecteeid:39,connectent:39,connectentitiesasync:39,connecting_collect:[17,18],connecting_ent:[17,18],connectorid:39,consid:[35,43,54,58,61],consider:[53,54,59],consoleappend:22,constrain:14,construct:[21,33,60,62],constructor:1,consult:70,consum:[29,62],contact:41,contain:10,containslook:11,containswil:11,content_typ:4,context:[1,29,39],contextu:29,continu:[11,26,41,65],contrast:[16,66],contribut:[21,28],contributo:21,contributor:46,control:[22,29,38,41,55,58,61,68],conveni:[9,53,63,65],convent:27,conversionpattern:22,cooki:56,coordin:36,copi:[0,16,22,23,41,65],core:[22,24,25,29,44],cores:25,correct:[30,35,43,45,56,65],correctli:25,correl:[35,38,39,43],correspond:[12,13,15,27,39,41,44,48,49,72],cost:29,costli:16,could:[2,11,16,26,38,39,53,54,58,59,63,64,66,67],couldn:39,count:[7,8,12,13,14,15,22,48,49,62],counter_nam:[6,8],coupl:[28,38],cours:22,cpu:38,creat:[2,5],createact:21,createadminus:21,createcollect:49,createent:[21,26],createev:21,creategroup:21,createnotif:21,createorg:21,createus:21,creation:[45,48,55,64],credenti:[21,22,23,25],criteria:29,cross:62,css:[31,44,68],cumul:6,curiou:70,curl:[4,5,6,8,9,11,12,13,15,17,18,19,20,22,24,25,31,32,34],current:[6,13,20,27,30,35,39,48,60,62,68],custom:[9,13],custom_id:9,custompayload:36,d0d7d0ba:12,d16344f5a0e1:20,d20976ff:63,d28c:72,d503:[2,27],d7a8:[15,49],d86a:12,d878de4r:55,d87edec7:62,d9693ec3:62,da448955:62,da4a50dc:15,da67:68,da71:68,da83:62,dai:[7,8,55],daili:8,dashboard:[35,56],data:1,databas:[11,14,16,20],datacli:[9,36,39,49,54,57],datastax:22,date:[10,36],dave:47,david:47,db1e60a0:[17,63,68],dbf5228024a7:[18,19],dbm:[11,12,14,16],dc5d478e9c029853fbd025bed0dc51f8:72,debug:[35,38,39,44],decim:10,declar:39,decompil:58,dedic:6,defin:[7,14,15,27,39,49,52,54,55,60,61,62,63,67,68,71],definit:[48,60],deflat:37,degre:[36,55],deleat:48,deleg:49,delet:[11,12],deletecollect:49,deleteent:49,delimit:[10,60,64],deliv:[29,36,41,44,48],deliveri:[29,36,48],denot:[63,66],depend:[22,37,39,40,63,64,72],deploi:21,deploy:21,deploywar:22,desc:11,descend:11,describ:[11,12,13,15,16,20,33,37,39,41,44,45,52,53,54,56,61,63,65,72],descript:[4,5,6,8,11,13,14,15,17,18,19,21,22,27,31,32,33,34,36,41,45,48,49,54,59,60,61,62],design:[14,16,20,23,29,30,44,62,63,64,65,67],desir:41,desktop:[37,41],destin:[1,36],destinationsingledevic:36,destroi:57,detail:[13,15,27,29,31,32,33,34,35,36,37,38,48,54,56,61,62,63,66,68,70],detect:[5,20],determin:[20,30,62,68],dev:[25,35,37,38],develop:[10,20,21,22,27],devic:[5,18,19,20,21,27,29,35],device_id:36,deviceid:[36,39,48],deviceregistrationcallback:39,devicetoken:39,deviceuuid:39,dfr4d5m1mjmoeeogvpncm:55,diagram:[35,38],dialog:[31,41,44],did:15,didfailtoregisterforremotenotificationswitherror:39,didfinishlaunchingwithopt:39,didregisterforremotenotificationswithdevicetoken:39,differenti:29,dimens:67,diner:11,dino:[66,72],dir:0,direct:[0,16],directli:[0,32,41],directori:[0,22,23,24,25,44,46,56,65],disabl:[23,31,34,45,48,71],disk:41,displai:[8,11,20,44,45,48,56,61,62,64,65],displayemail:48,displayemailaddress:[31,34],displaymessag:39,displaynam:[31,34,48,62],dist:22,distanc:20,distance_in_met:20,distinctli:28,distribut:[14,16,58],div:[31,68],dk88fh4r:19,dlog4j:22,doctyp:[31,68],doe:[0,15,22,27,35,43,45,48,49,53,54,55,56,62,63,68,72],doesn:[14,16,35,39,43,44,71],dog:[15,26,63,64,66,72],dogcreatecallback:26,doge:[63,64],domain:[41,56],don:[22,23,35,38,40,44,58,62,68],done:[0,22,23,25,29,37,39,41,48,56,58,59,68],dot:[6,10],doubl:[25,36,41],down:[10,22,28,36,39,41,61,69],download:[21,22],drive:[1,29],drop:[36,41,61,69],dropdown:69,dskiptest:[23,24,25],dtd:[31,68],due:[11,12,16,54],duplic:16,durat:[2,5,6,8,12,13,14,15,16,17,18,19,22,23,31,32,34,48,49,55,57,60,61,62,63,68,72],dure:[58,61],duti:61,e13743a7f1db7f4246badd6fd6ff54ff:68,e694:63,e7127751:63,e7d0:62,e8f5:[15,49],e94123890c7a:[15,49],e978:68,e97b:12,each:[0,6,7,8,10,12,13,14,15,16,20,22,27,31,35,36,38,41,45,48,49,50,56,59,61,62,63,68,71,72],earlier:[35,37,38,44],eas:29,easi:[0,29,67],easier:[9,11,12,16,35,58,63,66,71,72],easiest:61,easili:[6,20,27,29,58,67],east:23,easy_instal:0,eb20e5bce407:17,ebc6f49d1fc4:[15,49],ec2:22,ec39:72,edit:[0,1,21,22,23,41],edort1:31,ee912c4b:10,ef0b:[15,49],effb:[15,49],effect:29,effici:[12,16],either:[1,13,17,48,53,56,61],elastic_search_host:22,elasticsearch_cluster_nam:22,elasticsearch_host:22,elev:58,elimin:[29,53,58],els:[26,39,56],email:[12,22,23,24,25,27,31,34,38,41,45,48,54,62,63,65,68,72],email_address:[68,72],embed:25,embed_cod:47,employe:63,empti:[13,49,65],emul:[35,38],enabl:[20,23,29,35,38,39,40,41,44,45,56,58,61,62],enabledremotenotificationtyp:39,enabledtyp:39,enclos:[12,48],encod:[9,11,12,15,37],end:[8,21],end_tim:8,endpoint:[0,6,18,21,32,35],engag:[20,29],engin:22,enhanc:20,enough:[44,71],ensur:[10,16,22,29,35,36,38,41,44,52,54,58,72],enter:[31,36,37,41,44,56,61,65,68,69,71],entir:[11,36,48],entit:16,entiti:[0,2],entity_nam:15,entity_typ:[15,49],entity_uuid:15,entityid1:48,entityid2:48,entityid:[48,49,61],entityproperti:48,entitytyp:[31,34,48,61],entri:[11,36,56],environ:[37,44,58,70],equal:[10,12,39,55],equiv:[31,68],equival:10,err:[26,39,56],error:[6,21,22,25,26,34],errorcod:48,errormessag:48,escap:[36,49],essenti:[44,67],establish:[48,62,67],etag:[2,5],etc:[22,45],evalu:[10,23],even:[8,11,16,22,23,27,38,53,54,58,59,66],event:6,everi:[8,9,27,53,58,59,61,63,64,72],everyth:[0,22,72],exact:[20,67],exactli:11,examin:[8,58],exampl:[0,1],except:[15,35,39,43,53,58],exchang:41,execut:[9,11,12,25,26],exhaust:58,exist:[5,6,15,16,20,22,23,34,39,45,48,49,55,56,62,63],expect:[10,20,31,34,40,49,67],experi:[14,20,29,67],experiment:[52,71],expir:21,expires_in:[48,54],explain:[0,22,23,28],explan:26,explicit:41,explicitli:[39,53,57,61],expos:24,express:[10,11,22],extend:66,extens:65,extern:46,extract:[23,24,25,53,54,56,59],f18e8f6fb3bc:68,f315e5aa568a:[15,49],f322:49,f34f4222:[5,6,8,13,15,49,60,61,63,72],f399:62,f3a8061a:[15,49],f3aa:62,f3be262a:[15,49],f3teeg:32,f42752aa:49,f8zemolceecubwbqvsaaca:54,f_gubelxeecfrgbqvsaaca:54,facebook:[21,29],facebookaccesstoken:56,facebooktoken:56,factor:[22,23],fail:[35,36,39],failur:[14,48],fals:[10,22,23,25,31,34,48],famili:[14,20],familiar:[16,70],faq:23,far:69,fast:14,favorit:[25,38,39,68],favoritecolor:39,fb_access_token:[45,56],fbasynchinit:56,fbasyncinit:56,fc4d:62,fdd3:34,fe80:31,fe90:[31,34],featur:[16,20,21],feed:[5,12,18,19,21,29],feel:25,few:[11,20,35,40,65,67],ffd79647:62,field:[1,11,15,29,31,36,37,41,48,61],fieldset:[31,68],file_loc:5,filenam:5,files:1,filter:[12,62,63,68],find:[0,11,20,22,23,28,35,39],fine:[25,29],finish:[35,38,48,65],first:[0,10,11,12,13,16,25,26,31,35,37,40,41,43,44,45,49,58,61,70,72],first_nam:72,firstnam:[11,12,45],fish:24,fit:59,five_minut:8,fix:[35,43],flash:38,flexibl:[14,16,21,27],flow:[56,68],fluffi:24,fobnszewobnioerabnoiawegbrn:[5,61],focu:[29,72],folder:1,folk:[21,22],follow:[0,2,4,5,6,8,9,10,11,12,13,14,15,16,18,19,20,21,22,23,24,25,26,27,33,35,36,37,38,39,41,43,44,45,48],foo9876a:68,foo:72,footprint:[38,40],forappl:39,force_refresh:25,ford:[18,19,66,67],forgot:68,fork:46,forkei:[36,49],form:[15,22,27,31,34,36,48,49],format:[0,2,12,13,14,15,20,21,22,27,41,46,49,53,54,56,59,60,62],fornotifi:39,fortun:8,forward:[35,37,38,39,56,63],found:[32,53,54],four:[54,59],foursquar:62,fragment:56,framebord:47,framework:[38,65],francisco:[20,31,63,64],fred:[11,63,66],free:[25,27,35],friend:[18,20,29,38,61,62],from:[0,4,9,11,12],full:[11,15,22,29,31,33,35,38,44,53,54,58,59,61,66,71],fulli:[25,49,72],further:[26,33,39,45,53,56,58,72],furthest:[11,20],futur:[15,58],g9qgaaaurv_lfq7uu6ayhjjjn7qcrgovnvu:55,gain:[53,58],game:[7,38],ganyo:44,gatewai:41,gaufeolxeecfrgbqvsaaca:54,gcm:21,gcm_sender_id:44,gcmregistrar:39,gcmsenderid:39,gener:[0,6,7,21,24,25,27,30],geo:21,geocoordin:20,geograph:11,geoloc:11,get:[2,4,8,11,12,13,14,15],getapigeedeviceid:39,getclient:39,getcollect:49,getconnect:39,getdatacli:39,getent:49,getloggedinus:39,getregistrationid:39,getuniquedeviceid:[36,39],getuuid:39,ggkaaqmaggkabge5ffm1aqcadqaq_9ewr_ozeeguwxixowauaqcadqaqablaovoaeeguwxixowauaqa:62,ggkaaqmaggkabge5mlfh7gcadqaqjikhxefqeegw9hixowbregcadqaqjnep6ufqeegw9hixowbrega:62,ggkaaqmaggkabge5xc3r1gcadqaqz02yhp6qeegvybixoxisvgcadqaqz3soh_6qeegvybixoxisvga:34,ggkaaqmaggkabge5xc3r1gcadqaqz02yhp6qeegvybixoxisvgcadqaqz4zbyf6qeegvybixoxisvga:31,ggkaaqmaggkabge7pehcgwcadqaqvj9dljfzeekg9wloguza3acadqaqvkvrctfzeekg9wloguza3aa:62,git:[0,46],github:[21,23,28,44],give:[6,16,29,38,41,55,60,61,67,71,72],given:[10,15,16,27,34,47,48,53,58,71],gladi:12,gmail:[25,31,62,68],goal:[11,30],goe:[22,23],gold:24,good:[0,22,28,58,71],googl:[21,29,31],gool:[35,43],got:[35,38],gotten:[22,35,38],govern:[52,54,59,63],grain:29,grant:[48,53,54,56,58,59,61,72],grant_typ:[24,32,48,54,55],granular:[6,8],graph:[21,29],graph_async:25,graph_us:25,gravatar:[12,62,63,68,72],great:[29,45,61,63,64],greater:[10,11,55],greatest:59,green:22,groovi:0,group:[5,10,12,14,15,18,19,21,27],group_path:36,groupid:48,groupnam:[62,63],grouppath:63,groupproperti:48,grunt:46,gte:10,guarante:26,guest:[39,53,58,61,62,68,71],guid:[9,21],guidanc:44,gzip:37,hacker:[53,54,58,59],had:36,half_hour:8,hand:16,handi:70,handl:[29,31,39,67],handlepushnotif:39,happen:[20,38],happi:[0,62],happy_cloud:5,hard:[1,59],hardwar:[35,38],hava:0,have:[0,12,14,15,16,19,22,25,27,32,34,35,36,37,38,39,44,45,48,54,55,56,58,59,61,62,63,64,65,67,68,70,72],haven:22,head:[31,68],header:[4,53],heap:22,heavi:38,hector:22,height:[47,48,62],hello:62,help:[7,11,14,22,25,27,29,52,54],her:[16,31,38],here:[2,12,16,20,22,23,24,25,27,28,38,46,56,62,63,65,68,72],hierarchi:[6,27,33,34,60,63],high:[14,16,36,38,39,40,52,55],higher:[24,59],highest:[33,34],highlight:16,hike:59,him:24,histori:36,hold:[5,49],home:20,homepag:6,host:[22,23,25,53,56],hostconfig:22,hostnam:[22,25],hotmail:34,hour:8,hous:16,howev:[8,11,12,13,15,25,26,27,35,38,44,45,56,58,61,62,65],href:[31,34,68],html4:[31,68],html5:[21,22,35],html:[0,31,41,44,48,56,65,68],htmldisplayemail:48,htmldisplayemailaddress:[31,34],http:[2,4,5,6,8,12,13,14,15,16,17,18,19,20,21,22,23],httpd:22,human:[31,68],hundr:11,hurrai:56,hystrix:25,icon:[41,62,65],idea:58,ident:[16,44],identif:[44,48],identifi:[9,16,27,31,37,39,41,45,49,68],ifram:47,illlustr:39,illustr:[14,35,36,38,39,52],imag:[2,4,5,14,29,35,38,44,48,62],imagemodel:21,imagin:[12,16,36,59],immedi:[29,36,61,68],immut:27,implement:[29,35,39,52,53,54,56,59,68,72],implicit:61,improv:[20,29],inact:[39,61],inbox:[45,62,64],includ:[6,11,12,14,15,16,22,27,29,31,35,36,37,38,39,44,48,49,53,54,55,56,58,61,63,68,69,70,71,72],incorpor:65,incorrect:[31,72],increas:[13,20,29],increment_valu:6,index:[0,10,11,15,22,25,27,44,65],index_prefix:25,indic:[22,48,55,62,63],individu:[15,27,55,59],ineffici:[11,12,16],inflat:16,info:[22,31,48],inform:[4,8,11,12,13,14,15,16,20,23,27,29,31,33,35,36,37,38,39,41,44,45,46,49,52,53,56,58,62,63,65,66,68,70,72],infrastructur:[27,29],ing:62,inher:58,init:[22,36,49,56],initi:9,initwithobject:49,initwithorganizationid:39,inner:16,input:[31,68],insecur:58,insert:56,insid:72,instal:[0,9,21,22],instanc:[22,23,24,27,39,49,54,57,65],instead:[16,29,54,58,59,72],instruct:[0,22,23,35,46,56,65,68],integ:[11,48],integr:[20,29,35,56,72],intend:21,intention:16,interact:[35,43],interest:[8,29],interfac:[23,65],intern:21,interpret:[60,72],intersect:10,intrins:72,introduc:29,introduct:40,invalid:[45,56],invok:[35,38,39],iphon:65,isloggedin:39,isn:[14,39,52,70,72],iso:[31,68],isregisteredonserv:39,issu:[0,2,21,22,23,32],item:[10,12,13,15,36,49,62,72],items:13,itself:16,jan:22,jane:68,jar:[24,44],java:[0,22,23,24],java_opt:22,javascript:[6,9,12,14,21,22,23,26,31,35],javscript:26,jdk:[22,23,24,25],jdoe57:27,jenni:16,jersei:30,jim:31,jin:47,jinm:31,job:61,joex:39,john:[27,54,62,63,68,72],johnson:47,join:16,jpeg:[2,4,5],jpg:[2,5,14,16],json:[10,12,14,15,16,19,22,24,27,31,32,36,37,49,56,62,63,67,72],json_arrai:15,json_object:15,just:[14,16,17,20,23,35,38,40,44,62,67,71,72],k88dh4f:18,kbundledsoundnamewithext:36,keep:[1,7,9,11,12,29,35,38,40,53,54,58,59,71],kei:[13,15,16,21,29,35,37,38,39,41,43],keychain:[41,44],keyspac:[23,25],keyword:15,kid:16,kind:[11,12,16],know:[8,22,38,41],knowledg:22,known:39,kravitz:12,kugclientresponsesuccess:39,label:31,lack:71,lag:26,languag:[10,14,15,72],larg:[0,10,11,62],last:[5,11,27,34,45,48],lastnam:[11,12,45],lat:36,latenc:26,later:[16,20,36,41],latest:[23,24,44],latitud:[11,20,36],latitude_coordin:20,launch:[8,22,35,38,39,41,43,44,58],launchopt:39,layer:24,layout:22,lceecubwbqvsaaca:54,learn:[21,28,29,35,38],least:[22,23],leav:[23,41,61],left:[28,36,37,41,44,61,62,65,69],length:[2,5],less:[10,14,55,62],let:[8,22,24,29,36,38,61],letter:68,level:[6,8,14,15,21,22,24,27,29,32,33,34,35,36,39,44,52,53],leverag:[29,65],lib:[22,23,25,44],librari:[22,35,38,44],licens:22,lightweight:67,like:[0,2,5,8,10,14,16,17,18,19,22,23,25,26,29,31,35,36,38,45,56,58,60,61,62,64,65,66,67,68,71],liked_bi:66,limit:1,line:[0,16,22,23,24],linear:[14,23],linux:22,listen:38,live:[21,53],load:[24,56],localfilebinarystor:1,localhost:[22,23,24,25],localizeddescript:39,locat:5,log4:22,log4j:22,log:6,logger:22,login:[21,22],logincredenti:21,loginfacebook:56,loginus:39,logout:21,longer:[11,58],longitud:[11,20,36],longitude_coordin:20,look:[2,8,10,11,16,22,35,36,38,56,59,62,68],loos:[31,68],love:16,low:[38,40],lower:[6,10],lte:10,ltixndg0nduxndpvdjb0jwrevls1vcd0xvr3nwt0jrqq:11,lunch:38,mac:[35,38,41],machin:[22,41,44],made:[19,46,60,66,72],magic:16,mai:[0,6,9,10,13,15,22,27,36,37,39,44,48,57,58,61,63,71],mail:[23,25,27,63],mailer:[22,23,25],mailto:[31,34],main:[0,1,56],maintain:[16,56],make:[0,9,11,12,14,16,22,25,26,27,29,33,35,39,43,44,45,53,54,56,57,58,62,65,66,67,68,70,71,72],makefil:0,maker:14,malici:[52,53,54,59],manag:[5,11,12,21,22,23,24,25,27,28],managementappindexstatu:22,mandatori:[1,45,63,64,68],mani:[7,11,12,14,16,20,22,27,36,61,67,71],manual:[62,66],map:14,marginheight:47,marginwidth:47,market:38,massoddb:62,match:[11,15,22,25,35,43,44,49,60,68],matter:[29,35,38,44],mattress:14,maven:[0,23,24,25,46],max:25,maximum:[11,36,55],mayb:16,mean:[10,14,15,16,26,27,36,52,53,58,66,67,71],meant:62,meanwhil:26,measur:52,mechan:65,meet:23,member:[27,31,33,44,48,59,62,63,64],meme:[63,64],memori:[20,38],menu:[32,35,38,41,61,65,69],messag:[6,21,22,23,25,29,31],message:21,meta:[31,68],metadata:[2,4,5,6,10,12,13,14,15,16,17,18,19,20,21,31,34],metadataproperti:48,meter:[11,20,36],method:[6,8,11,15,19,21,26,31,32,33,34,35,38,39],mfdsadfdsaoabl:62,microsecond:22,middl:45,middlenam:45,might:[7,8,9,11,12,14,15,16,22,23,25,27,29,32,35,36,38,39,41,43,58,61,63,70],mile:20,milk:[13,15,49],million:29,millisecond:[27,48,55],mimic:30,mind:[1,9,11,12,16,20,35,38,71],minim:[16,22,23,25,30],minimum:[27,32,34],minu:16,minut:[8,29],mix:72,moab:62,mobil:[14,16,20,21,32,35,37,38,39],model:14,modern:[27,62],modif:[45,64],modifi:[2,5,6,12,13,14,15,16,17,18,19,20,27,31,34,44,45,48,49,55,61,62,63,64,68,72],modul:6,monitor:[22,29],month:[8,29],more:[4,6,8,9,11,12,13,14,15,16,20,21,22,23,27,28,29,34,35,36,37,38,39],morn:8,most:[8,11,16,25,26,27,28,29,32,58,62,66,67,68,70],mountain:59,move:[22,39,44],much:[10,14,16,58,65],multi:[15,22,49],multipl:[0,11],must:[0,10,15,16,22,24,25,27,34,36,37,38,39,41,44,48,49,53,55,61,62,63,65,66,68],mustach:0,mvn:[23,24,25],my_app:[14,16,45,56],my_org:[14,16,45,56],myadmin:24,myapp:[12,24],myasset:2,mycollect:10,myfirstorg:24,mygroup:[62,63],mynewapp:[63,68],mynewgroup:63,mynewpassword:31,myorg:[12,63],mypassword:24,myself:[16,23,25],myuser:24,name:[1,2,4,5,6,8,10,11,12,13,14,15,16,17,18,19,20,22,23,24,25,27,31,32,34,35,36,37,38,39,41,43,44,45,48,49,53,55,56,58,60,61,62,63,64,65,68,69,71,72],nanoc:46,narrow:[10,61],nativ:[0,14,39,44],natur:[11,12],nav:[36,37,41],navig:[23,24,25,44],nearbi:20,nearest:[11,20],nearli:16,necessari:[16,29,35,38,39,44,61],need:[0,1,2,8,9,11,12,13,14,15,16,22,23,25,27,28,29,31,32,33,34,35,36,38,39,40,41,44,45,53,54,56,57,58,59,61,62,63,65,66,67,68,69,70,72],neg:6,nest:[15,27,49],net:[47,72],network:29,never:[21,32,53,54,55],new_password:[31,68],new_review_uuid:16,newdevicetoken:39,newent:49,newli:[41,48,60,62],neword:36,newpassword:[31,48,68],next:[10,11,13,21,22,24,25,38,41,44,65,69],nil:[39,49],node:[22,23,25,49,50,54,57,72],nodej:25,noisi:22,non:[14,16],none:61,normal:[4,15,16],nosql:[11,12,14],notat:[10,12,14],note__:68,notic:[5,16,19,22,56,62],notif:[20,21,22,23,25,27,28],notifc:48,notifi:[21,27,35],notificationid:48,notificationupd:21,notifier_nam:36,notifiernam:39,notify_sysadmin_of_new_admin_us:[22,23,25],notify_sysadmin_of_new_organ:[22,23,25],now:[22,23,24,25,36,38,44,56,65],nsarrai:49,nsdata:39,nsdictionari:[39,49],nserror:39,nsexcept:49,nslog:39,nsmutablearrai:49,nsmutabledictionari:[36,49],nsstring:[36,49],number:[6,7,11,12,13,14,22,27,29,35,38,41,43,44,48,58,61,62,68],number_of_replica:22,numebr:48,oauth:[21,29,45,52],ob5ko:55,object:[5,9,10,12,14,15,21,27,29,31,32,34,36,39],objectforkei:39,objectproperti:48,objecttyp:[31,34,48],objectuuid:48,obtain:[45,53,55,56,58],occur:[7,20,35,43],occurr:11,octal:10,off:[23,36,39,56],offer:[20,29,58,66,67,71,72],offici:[22,65],often:[8,10,16,27,29,62],old:[31,48,68],old_password:[31,68],oldpassword:[31,68],omit:12,onc:[0,11,16,22,23,25,26,35,37,38,41,43,44,56,58,61,68],onexcept:39,ongo:[29,62],onli:[5,9,11,12,16,22,23,25,26,27,32,48,52,53,54,55,58,59,60,62,63,66,68,69,71,72],onlin:62,onrespons:39,oop:56,opdata:49,open:[14,16,21,25],optim:[11,12,14,16],option:[5,9,22,23,25,27,39,44,49,53,56],order:[2,10],orderl:11,org:[1,2,4,5,6,8,12,13,15,17,18,19,20,22,23,24,25,31,32,34,36,37,39,44,48],org_client_secret:54,org_clientid:54,org_id:[15,48,62,63,68],org_nam:[32,34,55,57],org_uuid:[32,34],organ:[0,2,4,5,6,8,12,13,14,15,16,17,18,19,21,22,23,24,25],organizationnam:55,organizations_require_activ:[22,23,25],orgid:48,orgnam:[9,39,44,48,54,56],orguuid:48,origin:[41,63],originali:64,oscar:24,otherwis:22,our:[0,9,10,11,12,23,24,25,28,36,46,49,67],out:11,outbox:62,outgo:[22,25],outlin:5,output:[22,39,56],over:[8,38,55],overrid:[25,39,55],overrideurl:22,overview:[11,12,21,27,29,36,37],overwritten:15,own:[7,22,29,36,48,56,60,62,63,64,68,71],owner:[2,34,48,62,63],p12:[35,37,38],p12certif:37,packag:[22,23,56,65],page:[22,24,31,36,37,41,54,56,70,71],pair:[13,15,36,49],pane:[44,61],param:[2,5,6,8,12,13,14,15,16,17,18,19,39,49,55,60,61,62,63,68,72],paramet:[4,5,6,8,9],parenthes:10,pars:56,part:[9,11,12,16,20,22,36,41,72],parti:22,partial:[11,27],particular:[10,16,36,62],particularli:[14,16,60,62,66],partit:70,pass:[11,32,39],passiv:67,password:[21,22,23,24,25],path:[2,5,6,12,13,14,15,16,17,18,19,20,21,22,23,25,31,34,35,36,43,44,48,49,56],path_to_imag:16,pathnam:56,pattern:[39,48,60],patternlayout:22,payload:[36,44,48],peak:8,peopl:[7,27,62,63,64,65],per:[13,14,56,61],perceiv:26,perform:[4,5,13,14,16,18,22,26,29,31,33,35,45,53,54,59,60,62,64,68],period:[7,8,20,61],permiss:[5,12,18,19,21],persist:[24,25,72],person:[16,20,22,28,31,34,41,65],perspect:27,pertin:33,pet:24,phone:12,phone_numb:12,phone_typ:36,phonegap:21,photo:[20,67],physic:20,pictur:[4,5,12,20,45,48,63,68,72],pinterest:62,pip:0,place:[14,15,16,22,23,27,28,49,54,68],plai:[7,38,70],plain:4,plan:16,platform:[29,35,36,37,38,39,40,41,44],pleas:[10,31,36,53,55,61,66],plenti:0,plu:22,plug:[35,39,44],plugin:[39,44],plural:[13,15,27,48],png:16,point:[10,11,14,20,22,25,26,29,30,56,65],polici:58,pop:65,popul:[63,65,67],popular:[29,65],popup:61,port:[22,23,24,25],portal:21,portion:[36,48],pose:55,posit:[11,20],possibl:[16,35,38,39,43,58,66],post:[2,5,6,7,13,15,16,17,18,21,24,31,32,33,34,36,37,39,44,48],postal:11,potenti:11,power:[20,24,27,29,47,54,59,66],practic:[11,12],precis:62,predefin:27,prefer:[11,23,35,72],prefix:32,prepar:58,prerequsit:21,present:[16,21],preserv:63,press:[35,43,44],prettyprint:22,prevent:[11,12],preview:0,previou:[41,62,65],previous:65,price:[10,13,15,49],primari:[16,45],prior:58,privaci:62,privat:29,privileg:34,probabali:22,probabl:[0,16,22,23,26,28],problem:25,process:[24,27,31,38,39,48,67],product:[14,16,21,22,23,27,36,37,41,52],product_uuid:[14,16],productid:16,productimag:16,productnam:16,productuuid:16,profil:[20,29,35,38],program:26,programat:69,programmat:[21,32],progress:36,project:[0,24,28,30,33,34,35,38,41,43,44,46,65],prompt:[23,44,56],prone:62,proof:[31,68],prop:49,proper:44,properit:20,properli:[24,26],properti:[1,4,5,6,9,10,11],properties____:23,property_1:[13,15],property_2:[13,15],property_nam:11,props1:49,props2:49,propti:31,protect:[52,54],protocol:[22,23,25,56,58],prototyp:56,provid:[6,8,11,13,14,15,20,22,25,27,29,31,32,34,36,37,38,39,41,44,45,48,49,50,53,54,56,58,59,61,62,63,65,68,69,72],provis:[35,38],proxim:[11,20],pull:[38,39],pure:72,purpos:[10,22,23,27,32,61,67,71],push:[0,20,21,28],pushalert:36,pushapp:41,pushnotif:39,pushtest:44,pushtest_dev:37,put:[5,12,13,15],pw123:23,pwhere:25,python:0,qualifi:72,quantiti:10,query_stat:12,query_str:[63,68],querystat:48,querystr:49,queue:[36,48],queuedepth:22,quicker:72,quickli:[11,12,16,27,29,67],quiet:22,quitwait:[23,25],quot:[12,36,48,49],radiu:36,raleigh:47,rang:8,rate:16,rather:[5,16,17,18,29,39,41],raw:0,rawrespons:[36,39],rdbm:[14,16],reach:[10,21,38],reactiv:21,read:[9,11,12,14,16,40,48,62,70],read_phone_st:44,readabl:16,readi:[11,22,25,65,70],readm:[0,28,35,39,46],real:48,reason:[38,63],recaptcha:[31,68],recaptcha_challeng:48,recaptcha_challenge_field:31,recaptcha_respons:48,recaptcha_response_field:31,recaptchaopt:31,receipt:[21,27],receiptid:48,receiv:[11,26,35,38,39,40,41,45,48,64,65,68],reciev:48,reciproc:66,recommend:[22,23,49,58],record:[27,29],recreat:[35,43],recurs:60,redefin:61,redirect:[22,23,25,44,56],redirect_root:[22,23,25],redirect_uri:56,reduc:[12,16],redund:16,regard:[6,27],regardless:15,regid:39,regionnam:1,regist:[21,29,35,37,38],registerdevic:39,registerdeviceforpushasync:39,registerforremotenotificationtyp:[35,38,39],registerpush:39,registerwithpushprovid:39,regularli:38,rel:[31,68],relat:[5,14],relationship:[16,17,18,19],releas:22,relev:[20,29,56,58,67],reli:16,rememb:[10,36,41,56,65],remind:16,remot:[20,39],remov:[21,23,31],removeent:49,renam:[22,27],repeat:65,replac:[1,16,44,56,65],replic:[22,23],replica:22,replication_factor:[23,25],repo:[23,25,28,46],report:[7,22],reposloc:1,repres:[11,14,27,29,31,34,35,37,39,48,59,60,62,63,68,69,72],represent:[11,15,27,72],request:2,requir:[0,6,13,17,18,20,21,22],resend:36,reserv:27,resetpw:[21,22,23,25,31],resetpwmsg:21,resolut:8,resourc:[0,1,21],resource_path:60,respect:53,respond:[35,43],respons:2,response_typ:56,restart:22,restaur:[11,20,38],restkit:65,restrict:[58,61],restructuredtext:0,result:[10,11,13],retri:36,revers:41,review_entity_json:16,review_uuid:16,reviewed_product_uuid:16,reviewedbi:16,reviewedin:16,revok:21,revoketoken:57,rich:[29,67],right:[16,22,26,38,61,62,65,67,72],rigid:27,risk:55,rock:10,rockadero:20,rocki:59,role:[5,10,12,18,19,21,27],roleid:48,rolenam:[5,12,18,19,45,48,61,63,64,68,72],roleproperti:48,roll:22,root:0,rootlogg:22,rout:[29,62],row:14,rpc:22,rubi:[49,50,72],rule:[10,52,54,58,59,60,61,63,68,71],run:[0,7,21,22],safe:59,sai:[8,53,54,62],sake:25,sale:38,same:[5,6,11,16,18,19,20,22,27,29,35,36,39,43,44,48,59,61,62,63,64,65],sampl:21,san:[20,31,63,64],sandbox:[5,15,21,27,34,35,36,39,44,45,48,49,52,53,56],santa:47,save:[5,15],scalabl:[14,16,23],scale:[16,22],scatter:16,scene:[45,56],schedul:[21,35],schema:[14,27,48,61],scope:[16,24,54,56,59],screen:[44,47,69],script:[0,22,31,59,68],scroll:47,sdk:[6,9,14,15,21,22],search:[8,11,22,29],second:[6,26,31,36,55,61,65],secondari:16,secret:[21,32,48],secretkei:1,section:[32,35,36,41,44,48,53,54,63,65,68,72],secur:[21,22,29,41,44],see:[2,4,8,9,10,11,12,13,14,15,19,20,22,23,24,25,27,29,31,32,33,34,35,36,37,38,39],seek:22,seen:62,segment:60,select:[10,11,12,16,36,37,41,44,61,63,65,68,69,71,72],self:[36,39,56],send:[1,4,9,11,12,19,20,21,24,29,31,34],sender:[35,38,41,43],senderid:44,sendmyselfapushnotif:36,sens:[16,29],sensit:[52,71],sent:[9,12,21,31,32,34],separ:[6,12,16,22,27,35,36,37,38,39,41,46,49,56,61],seri:[0,22],serv:[22,58,59,61],server:[11,22,23,26,29,32],servic:[1,12,20,21,22,24,29,31,33,34,35,36,37,38,39],servlet:22,session:[56,58],set:[0,4,5,6,8,11,12],setapiurl:39,setapplicationid:39,setdevicepushtoken:39,setenv:22,setlog:39,setobject:49,setorganizationid:39,settoken:56,setup:21,setvalu:36,sever:[1,72],share:[22,24,34,62,67],sharedappl:49,she:38,shell:[22,70],shoot:22,shorthand:11,should:[0,2,11,12,15,16,17,18,22,23,25,28,35,36,37,38,39,41,44,46,48,49,52,53,54,55,58,59,61,65,70,71],show:[12,13,16,35,36,49,61,65],shown:[9,10,11,12,13,15,19,22,31,35,36,38,43,44,53,56,62,63,68],side:[28,29,32,53,54,56,58,59,65],sidebar:61,sign:[21,22,23,25,27,29],similar:[16,41,62,65],simpl:[0,14,16,23,27,29,35,65,67,71],simplest:22,simplestrategi:[23,25],simpli:[13,19,29,61,62,65,72],simplifi:[16,29],simultan:36,sinc:[10,11,26,53,59],singl:[8,12,14,15,16,22,23,27,29],singular:27,site:[37,41,46],six_dai:8,size:[10,22],skill:22,skim:[15,49],sku:[14,15,49],slash:[63,64],slate:61,slideshar:47,slideshow:47,slightli:14,slower:10,small:23,smith:11,smtp:[23,25],snippet:56,social:[20,21],softwar:[22,25],sojre5ywlkq7jrdcka:54,solid:47,solut:27,solv:29,some:[0,1,7,9,11,16,22,24,25,26,27,58,61,62,63,65,72],somegroup:63,someon:[8,36,61],somepassword:[23,55],somesubgroup:63,someth:[2,16,22,23],sometim:[0,14,35,43],someus:[23,55,57,61,63,68,72],soon:21,sort:[11,20,72],sound:[36,39],sourc:[0,14,16,21,22],space:16,span:[8,16],sparingli:59,special:[0,20,38,60,61,66],specif:[7,10,11,14,15,16,19,27,29,35,36,37,38,39,44,48,49,53,57,59,60,61,62,63,68,72],specifi:[6,11,12,13,15,17,18,19,20,22,23,33,34,36,37,39,48,49,53,54,55,60,62,63,65,68,72],split:8,sql:[10,16,29],squar:15,src:[0,1,31,44,47,68],ssl:[35,38],stack:[1,21],stage:25,standalon:24,standard:[20,22,39,44,58,59,68,72],standardengin:22,start:[8,11,12,14,16,21],start_tim:8,startintern:22,startup:[22,24],state:[31,39,48,56,72],statement:[12,26,48],statist:7,statu:[12,22,23,24,25,30,31,34,39,48,56,67],stdout:22,step:21,steventraut:[63,68],still:[35,43,58,70],stock:[13,15,23,38,49],stop:[11,36],store:[1,5,10,11,12],str:62,strateg:16,strategi:[23,25],stream:20,streamlin:[16,65],string:[9,10,11,12,13,15,16,27,31,32,34,36,39,45,48,49,53,56,62,63,64],stringifi:56,strong:31,stronger:20,structur:[16,24,33,66,72],struggl:62,style:[29,31,47,52,62,65,68],stylesheet:[31,68],sub_properti:15,subgroup:63,submit:[11,12,31,36,41,46,60,68],subproperti:49,subproperty1:49,subproperty2:49,subscrib:[62,63,64],subscript:[63,64,66],subsequ:[45,48,53,54,56],subset:[13,16,36],substitut:62,subtract:10,succe:[45,56,60],succeed:39,success:[22,23,26,44,48,49,58],successfulli:[35,43],sudo:0,suffix:41,suggest:[20,71],suit:[54,59,61],summit:47,sungju:47,super_user_email:22,super_user_password:22,superadmin:23,superus:[22,23,25],suppli:[31,34,48,54],support:[0,8,10,14,16,20,21,22,23,26,27,29,32],suppos:15,supprt:44,sure:[22,25,35,38,43,44,52,58,65,69,71],swagger:[0,30],symbol:68,sync:21,synchron:21,sysadmin:[22,23,25],system:[0,14,22,23,25,27,39,41,45,46,48,55,62,63,65,68],tab:[35,37,38,44,61],tabbi:10,tag:[39,48,56],tail:22,take:[6,11,16,25,26,29,41,52,54,58],taken:[20,39,56],tale:[10,11],talk:[25,47,58,65],tap:44,tar:[22,56],target:[0,21,23,24,25,29,35],task:61,team:[33,34,44,65],technic:56,techniqu:[11,16],technolog:44,tell:[22,35,38],temp:1,templat:[0,22,44],temporari:1,tempt:[16,41],tend:[63,64],termin:44,test12345:[31,34],test1234:68,test123:[31,34],test:[5,11,22,23,25,34,35,38,44,58,59,63,65,71],test_admin_user_email:22,test_admin_user_password:22,testadmin:54,testadminpw:54,testapp1:[32,34],testapp2:34,tester123:34,tester:48,testorg:[32,34],testpw:54,text:[4,10,11,29,31,36,62,65,68],text_field:31,than:[0,5,6,8,10,11,12,13,16,17,18,23,29,39,41,44,55,58],thank:29,thei:[0,10,11,12,15,16,20,27,34,38,39,40,52,53,54,58,59,61,62,63,64,68],them:[0,6,9,10,11,12,16,22,29,35,36,38,39,44,54,56,59,61,62,71,72],theme:[16,31],themselv:68,thereaft:52,thereof:36,thi:[0,1,2,6,8,9,10,11,12,13,14,15,16,20,22,23,24,25,26,27,28,29,30,31,32,35,36,37,38,39,40,41,43,44,45,48,49,52,53,54,55,56,57,58,59,61,62,63,64,65,66,67,68,69,70,72],thing:[7,10,22,28,35,38,40,47,52,63,64,68,70,71],think:62,those:[11,16,22,25,38,39,44,52,53,54,58,59,62,68],though:[10,11,16,36,41,48],thousand:14,threadpool:25,three:[6,11,22,23,25,35,59,61,65],through:[14,16,29,32,33,34,39,41,45,48,52,56,58,59,62,63,68,69],thumb:71,tier:24,time:[6,7],timeout:25,timer:22,timestamp:[2,5,6,8,10,12,13,14,15,16,17,18,19,22,23,27,31,32,34,36,45,48,49,55,57,60,61,62,63,64,68,72],timinglogg:22,tip:[36,37,39,44],titl:[10,11,16,31,34,36,39,48,61,63,64,68],tld:[22,23,25],tmp:1,toctre:0,todai:20,togeth:[0,59],token:[9,13,15,21,24,31,32,33,34,35,36,38,39,45],token_to_revok:57,tom:60,tomcat7:22,too:0,tool:[9,11,12,21,29],top:[24,35,36,44,56,65,69],topic:[11,28,36,49,50,54,63,64,68],topolog:23,tostr:39,track:[6,7,45],trail:59,transactionst:39,transfer:72,transform:0,transit:[31,68],transport:[23,25],treat:[15,21],trend:29,tri:22,trial:72,troubl:22,troubleshoot:21,truli:29,trust:41,tsefia:31,ttl:21,ttl_in_millisecond:55,tupl:14,turn:[36,38,56],tutori:21,tweet:[29,62],twitter:[29,62,65],two:[10,11,12,24,26,27,31,37,39,49,53,65,66,67],type:[2,4,5,6],typic:[10,27,68,72],udpat:0,uffff:10,uiapplic:[39,49],uiapplicationlaunchoptionsremotenotificationkei:39,uiremotenotificationtyp:39,uiremotenotificationtypealert:39,uiremotenotificationtypesound:39,unauthent:61,under:[23,36,41,44,54,57,58,61,65,71],underli:[14,39],understand:[27,44],unencod:[9,11,12],unexpect:48,unfamiliar:14,unfortun:0,unicod:10,uninstal:[35,43],union:10,uniqu:[15,27,37,39,41,45,48,56,63,64,65,68],unit:22,univers:27,unix:[6,22,36,45,48,64],unix_timestamp:36,unless:[0,36,45,53,56,59,65],unlik:[14,15,27],unlock:[35,43],unnecesari:58,unregist:61,unreleas:21,unsecur:58,unsent:21,until:[26,35,43,48,61],untrust:58,untrustworthi:21,unus:61,upcom:20,updatecollect:49,updatedent:49,updateent:49,upon:72,uptim:22,upward:6,uri:[2,5,6,8,9,12,13,14,15,16,17,18,19],url:[9,11,12,13,15,16,19,21,22,23,25,33],usag:8,usegrid:22,user:[5,7,10,11,12,13,15,16,17,18,19,20,21,22],user_uuid:16,user_uuid_or_usernam:57,usergrid_appl:25,usergrid_cluster_nam:22,usergriddatacli:[54,57],usergridsdk:56,userid:48,userinfo:39,usernam:[11,12,15,17,18,19,22,23,24,25,27,31,34,35,36,39,44,45,48,52,54,55,58,59,60,61,62,63,65,66,68,72],username_or_email:68,useruuid:39,usingnotifi:36,usr:22,usual:23,utc:[27,48],util:[24,27,29],uuid:[2,4,5,6,10,12,13,14,15,16,17,18,19,20,27,31,32,34,36,39,45,48,49,55,56,60,61,62,63,64,68,72],uuid_for_selected_review:16,vagrant:22,vagrantfil:22,val:56,valid:[1,13,15,22,27,31,32,34,36,37,44,45,53,55,56,58,60,61,62,63,64,68],valu:[1,6,8,10,11],valuabl:29,value_1:[13,15],value_2:[13,15],vari:8,variabl:[22,39,60],variei:22,varieti:[15,33,49,68,72],variety_1:49,variety_2:49,variety_3:49,variety_list:49,variou:[36,58],verb:[16,31,34,48,62],veri:[0,11,12,27,53,62,70],verifi:[37,41,44,52],version:[22,23,25,35,36,41,43,44,65],versu:62,via:[0,21,22,23,27,31,34,36,41],vibrat:44,video:[5,21,29,35,40],view:[8,16,22,23,25,35,36,38,41,44,59],virtual:[22,35,38],visit:[23,35,38,41],visitor:59,w3c:[31,68],wai:[6,11,12,14],wait:[11,26,35,39,43],walkthrough:[35,38,44],wall:62,want:[0,1,5,6,11],warn:[22,36,53,54,59,61,71],watch:[22,23,35],weakself:36,web:[12,14,16,22,23,24,32,35,37,38,41,44,45,46,54,56,58,59,67],webapp:[22,23,24],week:8,welcom:[22,23,25],well:[20,22,23,29,35,38,44,57,58,62,65,66,67,68,72],went:23,were:[11,12,20,44,63,64],what:[16,20,21,22,23,27,29,35,36],whatev:71,whatsoev:52,when:[0,5,9,10,11,12,15,16,17,20,21,22,23,25,26,27,29],whenev:56,where:[0,2,10,11,12,16,20,22,25,27,35,36,41,44,45,56,58,62,68,70,71,72],wherev:22,whether:[37,45,48,53,67],which:[0,8,11,13,14,15,16,18,22,23,26,27,31,33,35,36,37,38,39,41,43,44,45,48,52,53,54,55,56,58,59,60,62,63,64,66,68,69],who:[16,28,29,48,52,54,58,61,62],whole:[15,48,49],whose:[11,12,19,35,38,39,43,61,68,72],why:23,wide:[59,68],width:[47,48,62],wildcard:[11,60],window:[22,39,41,44,56,65,70],wireless:20,wish:[13,22,27,36,68],within:[6,11,15,20,23,27,34,36,48,55,59,62,65],without:[11,25,53,61,68],won:[35,38,44,62],word:[11,13,14,15,16,35,38,62],work:[0,11,12,14,16,20,21,22,23,25,26,28,29,37],world:62,would:[4,8,9,11,16,19,20,22,23,31,53,55,56,58,59,60,62,63,64,66,68],wouldn:16,write:[14,16,52,65],written:[0,14,16,23,28,35,46],wrong:23,wrote:16,www:[12,31,44,47,56,62,63,68,72],xcode:[35,38,44],xcodeproj:44,xfbml:56,xml:[1,44],xput:22,yaml:0,yea:44,year:62,yellow:22,yet:[11,35,38,48,63],yhixpqk1cq:32,yml:25,you:[0,1,2,4,5,6,7,8,9,10,11,12,13,14,15],your:[0,1,4,5,6,7,8,9,10,11],your_app_id:56,your_domain:56,your_redirect_url:56,your_response_typ:56,your_state_valu:56,yourapp:9,yourappnam:56,yourdomain:72,yourorg:9,yourorgnam:56,yourself:[35,43,44],ywmt4nqe8q9geelyjhixpsio4aaaato5fqfcg0ced2h9nwmdmrorknnreeqydof:31,ywmtfeewemyneektbnx3o4pu0qaaat8vzk3xz3utvzat0cosiym75c2qpigt79c:37,ywq6aaabmqz_xuyyeerokkjnzn7yqxxlpgml69fvaa:54,yxa65gylqja8ayysay8ox3vg5arzp48:32,yxa6aaabmq0d4mep_ugbza0:54,yxa7ygil:32,yxb7nad7em0meej989xixprxekq:54,yxb7nautv9krhhmr8ycw0qbozh2pxef:54,yxu6aaabmq0hdy4:54,zero:22,zip:56},titles:["Apache Usergrid Documentation","File storage configuration","Folders","<no title>","Retrieving assets","Uploading assets","Creating & incrementing counters","Counters & events","Retrieving counters","Advanced query usage","Query operators & data types","Query parameters & clauses","Querying your data","Collections","The Usergrid Data Store","Entities","Data Store Best Practices","Connecting entities","Disconnecting entities","Retrieving connections","Geolocating your Entities","Apache Usergrid Documentation","Usergrid 2.1.0 (unreleased) Deployment Guide","Usegrid 1: Deploying to Tomcat","Usegrid 1: Launcher Quick-start","Usergrid 2: Deploy to Tomcat","Async vs. sync calls","Usergrid Data model","Getting Started","Usergrid Features","jersey2skeleton","Admin user","Application","Organization & application management","Organization","Adding push notifications support","Creating and managing notifications","Creating notifiers","Getting started with push notifications","Managing users and devices","Push notifications overview","Registering with a notification service","COMING IN USERGRID 2","Troubleshooting","Tutorial: Push notifications sample app","Users & Devices","How to Contribute Code & Docs","Presentations & Videos","Methods","Usergrid iOS SDK","Usergrid SDK Documentation outline","COMING SOON...","Security & token authentication","Authenticating API requests","Authenticating users & app clients","Changing token expiration (time-to-live)","Facebook sign in","Revoking tokens (logout)","Security best practices","Authentication levels","Using permissions","Using roles","Activity","Working with group data","Groups","App Example - Messagee","Social Graph Connections","User management & social graph","Working with User Data","Creating a new application","Creating a Usergrid Account","Using a Sandbox Application","Using the API"],titleterms:{"default":[27,55,58,61],"new":[69,71],"return":68,"super":23,about:44,access:[48,53,58,72],accesstokenrespons:48,account:[65,70],acquir:58,action:48,activ:[29,31,34,48,49,50,62,67],activityfe:48,add:[22,23,56],addit:[22,44],addrol:48,admin:[31,34,36,37,48,49,50,54,57,59,61],advanc:9,all:[9,19,36],android:[35,38,39,43,44,65],apach:[0,21,47],api:[0,9,24,44,53,72],apn:[35,38,41],app:[20,35,40,41,43,44,47,48,49,50,54,56,58,65],appdata:48,appl:[35,37,38,41],applic:[27,28,29,32,33,34,48,49,50,54,69,71],asset:[2,4,5,29],assign:[49,50,60,61],async:26,asynchron:26,attach:9,audienc:22,authent:[29,49,50,52,53,54,59,72],backend:47,base:72,basic:12,batch:13,befor:44,begin:44,best:[16,58],between:0,build:[0,23,24,25,40,46,47,49,50],call:[9,26],can:40,cancel:36,cassandra:[22,23,47],certif:[41,44],chang:[55,68],claus:11,client:[34,40,49,50,53,54,58,65],code:46,collect:[13,27,48,49,50,64,72],come:[42,51],complet:31,complex:60,comput:16,configur:[1,22,23,44,59],connect:[17,19,35,39,49,50,66,67],consol:23,construct:72,contain:11,content:0,contribut:[46,47],contributo:28,counter:[6,7,8,49,50],creat:[6,13,15,31,32,34,36,37,40,41,44,49,50,55,56,61,62,63,65,66,68,69,70,71],createact:48,createadminus:48,createent:48,createev:48,creategroup:48,createnotif:48,createorg:48,createus:48,credenti:[32,34,48,49,50],curl:[36,39],cursor:11,custom:[15,23,49,50],data:[4,10,12,14,15,16,20,27,29,44,49,50,63,68],databas:[22,23],deal:0,decrement:6,delet:[13,15,36,49,50,63,68],denorm:16,deploi:[22,23,25],deploy:[22,25,28],descript:63,dev:44,develop:28,devic:[36,39,40,45,48],dialog:56,differ:0,directli:44,disconnect:[18,49,50],displai:68,doc:[0,46],document:[0,21,46,50],download2:24,download:[23,24,44],edit:58,elasticsearch:22,emul:43,end:22,endpoint:[36,37],enrich:20,entiti:[4,13,15,17,18,19,20,27,29,44,48,49,50,72],error:[35,43,48],event:[7,48,49,50],exampl:[4,5,6,8,13,15,22,23,25,31,32,34,49,50,54,55,56,57,60,61,62,63,65,68],expir:[36,55],facebook:[45,56],fail:43,featur:29,feed:[31,34,49,50,62,67],file:[0,1,22,23,25,29],find:40,flexibl:29,folder:2,folk:28,follow:[49,50,62,66],form:68,format:72,from:[13,34,35,43,49,50,63],gcm:[35,38,41],gener:[32,34,41,44,49,50,64],geoloc:[20,29],get:[16,22,23,24,28,31,32,34,36,38,40,49,50,68],github:46,googl:[35,37,38,41],graph:[66,67],group:[29,36,48,49,50,62,63,64,67],guid:22,handl:68,hierarch:6,how:[0,35,38,46,47],html5:[39,65],http:[24,58,72],imagemodel:48,increment:[6,49,50],initi:[22,31],instal:[23,43,49,50],intend:22,intern:47,interv:[8,49,50],invalid_send:[35,43],invok:56,issu:72,itself:25,java:25,javascript:[39,56,65],jersey2skeleton:30,kei:44,launcher:24,learn:40,let:68,level:[54,59],limit:11,link:2,list:2,live:55,local:[1,25],locat:[11,20,36],log:22,login:[23,29,49,50,54,56],logincredenti:48,logout:[49,50,57],manag:[29,33,36,39,40,49,50,67],markdown:0,messag:[35,36,43],message:65,metadata:48,method:[48,72],mismatchsenderid:[35,43],mobil:[47,58],model:[16,27,48],more:[40,44],multipl:[12,15,36,49,50],never:58,next:70,note:0,notif:[29,35,36,38,40,41,44,48],notifi:[36,37,40,44],notificast:36,notificationupd:48,oauth:[56,72],object:48,open:[28,47],oper:[10,28],order:11,org:[49,50],organ:[27,33,34,48,49,50,54],other:[0,44,49,50,66],out:16,outlin:50,overview:[38,40,47],p12:41,paramet:[11,36,63],parti:29,password:[31,49,50,68],path:60,permiss:[29,48,49,50,58,60],phonegap:[35,38,39,43,44],piec:35,portal:[22,25,36,37,61],post:[49,50,62],practic:[16,58],pre:16,preced:10,prerequisit:[0,38,40],prerequsit:22,present:47,product:58,profil:44,programmat:37,properti:[12,15,22,23,25,27,45,49,50,64],provis:44,publish:0,push:[29,35,38,40,43,44],put:16,queri:[9,10,11,12,16,20,29,49,50,72],quick:24,reach:40,reactiv:[31,34,49,50],receipt:[36,48],refer:[0,49,50],regist:[39,40,41,44],registr:29,relat:16,relationship:[29,45],relationshop:45,remov:[34,49,50,60,61,63],request:[4,5,6,8,12,13,15,17,18,19,31,32,34,36,53,54,55,57,60,61,62,63,68,72],requir:[23,24,25,35,37],reset:[6,31,49,50,68],resetpw:48,resetpwmsg:48,resourc:22,respons:[5,6,8,12,13,15,31,32,34,54,55,60,61,62,63,68,72],rest:[0,68],result:16,retriev:[2,4,8,12,13,15,16,19,34,49,50,62,63,68],review:[16,44,58],revok:[49,50,57],role:[29,48,49,50,58,61],root:22,rst:0,run:[23,24,25,44],sampl:[35,44],sandbox:[58,71],save:20,schedul:36,sdk:[25,49,50,54,56,65,72],secret:53,secur:[52,58,69,71],see:40,send:[35,40,43,44],sent:36,server:[35,43],servic:[41,44],set:[13,31,35,36,40,45,48,49,50,64],setup:[22,23,38,44,56],sign:[41,45,56],singl:36,social:[29,66,67],soon:51,sourc:[28,47,49,50],sphinx:0,ssl:41,stack:[22,25],start:[22,23,24,28,38,40,49,50],step:[22,44,56,65,68,70],storag:[1,29],store:[14,16],stream:29,sub:[15,48,49,50],support:[35,40,72],sync:26,synchron:26,syntax:[4,5,6,8,12,13,15,17,18,19,54,55,57,60,61,63,68],tabl:0,target:36,third:29,time:[8,49,50,55],token:[48,49,50,52,53,55,57,58],tomcat:[22,23,25],tool:44,treat:58,tri:[35,43],troubleshoot:[35,40,43],ttl:55,tutori:[35,40,44],type:[10,19,48],unreleas:22,unsent:36,untrustworthi:58,updat:[0,5,13,15,31,49,50,68],upload:5,uri:[31,32,34,62,63,68],url:[34,72],usag:[9,12],usegrid:[23,24],user:[23,29,31,34,36,39,40,45,48,49,50,54,57,59,62,63,65,67,68],usergrid:[0,14,21,22,23,25,27,29,42,44,46,47,49,50,65,68,70],valu:12,via:[44,46],video:47,wai:[16,58],want:16,war:[22,23],websit:[0,46],what:[38,40,71],when:[35,43,55],work:[38,43,49,50,63,68],you:[16,40,44],your:[12,16,20,35,40,43,49,50,58]}}) \ No newline at end of file diff --git a/content/docs/security-and-auth/app-security.html b/content/docs/security-and-auth/app-security.html new file mode 100644 index 0000000000..7bf7ecafac --- /dev/null +++ b/content/docs/security-and-auth/app-security.html @@ -0,0 +1,334 @@ + + + + + + + + + + + Security & token authentication — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Security & token authentication

+

Any app you put into production should feature security that protects +your app, your users, and your app’s data. Implementing security means +taking steps in your mobile app’s code and in your API Services BaaS +application.

+

Important: When you register for the API Services BaaS, you get a +sandbox application that you can use to try things out. This application +is not for use in production. By default, the sandbox application is not +protected by any security measures whatsoever. Use the sandbox only for +experimentation, and only with data that isn’t in any way sensitive.

+

When securing your app, follow these high-level steps:

+
    +
  1. Define the rules that will govern access by your app’s users to your +app’s data and features. You do this with the admin portal by +creating permission rules, then associating those rules with your +users. For more information, see Using +Permissions.
  2. +
  3. Write code through which your app’s users can verify who they are to +your application. You do this by writing code that uses their +username and password as credentials to initially authenticate with +your application, then uses a token thereafter. (This authentication +style supports the OAuth 2.0 model.) For more information, see +Authenticating users & app +clients.
  4. +
  5. Be sure to use coding best practices that help ensure that your app +is protected from malicious attacks. For more information, see +Security best practices.
  6. +
+

The following illustration describes these high-level areas.

+../_images/securitymodel0.png +
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/security-and-auth/authenticating-api-requests.html b/content/docs/security-and-auth/authenticating-api-requests.html new file mode 100644 index 0000000000..fc04d5d683 --- /dev/null +++ b/content/docs/security-and-auth/authenticating-api-requests.html @@ -0,0 +1,383 @@ + + + + + + + + + + + Authenticating API requests — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Authenticating API requests

+

With the exception of the ‘sandbox’ application that is created with +every Usergrid organization, all applications are secured by default. +This means that to access your data store, a valid access token must be +sent with all API requests to authenticate that the requester is +authorized to make API calls to the resources they are attempting the +access.

+

This article describes how to use access tokens to access the Usergrid +API, and how to manage access tokens, including revoking and changing +token time to live.

+

For information on generating access tokens/authenticating users and +clients, see Authenticating users and application +clients.

+
+

Authenticating with access tokens

+

When you obtain an access token, you must provide it with every +subsequent API call that you make. There are two ways to provide your +access token.

+

You can add the token to the API query string:

+
https://<usergrid-host>/{org-name}/{app-name}/users?access_token={access_token}
+
+
+

You can include the token in an HTTP authorization header:

+
Authorization: Bearer {access_token}
+
+
+

Note

+

+ + +Note: The Usergrid documentation assumes you are providing a valid

access token with every API call whether or not it is shown explicitly +in the examples. Unless the documentation specifically says that you can +access an API endpoint without an access token, you should assume that +you must provide it. One application that does not require an access +token is the sandbox application. The Guest role has been given full +permissions (/** for GET, POST, PUT, and DELETE) for this application. +This eliminates the need for a token when making application level calls +to the sandbox app. For further information on specifying permissions, +see Using Permissions.

+

+
+

Authenticating with client ID and client secret

+

Another option for authenticating your API requests is using either your +organization client ID and client secret, or your application client ID +and client secret, which will authenticate your request as an +organization or application admin, respectively. Organization +credentials can be found in the ‘Org Overview’ section of the admin +portal, and application credentials can be found in the ‘Getting +Started’ section of the admin portal.

+

WARNING

+

+ + +Warning: For server-side use only You should never authenticate this

way from a client-side app such as a mobile app. A hacker could analyze +your app and extract the credentials for malicious use even if those +credentials are compiled and in binary format. See Security Best +Practices for +additional considerations in keeping access to your app and its data +secure.

+

This can be a convenient way to authenticate API requests, since there +is no need to generate and manage an access token, but please note that +you should be very cautious when implementing this type of +authentication. Organization-level authentication grants full permission +to perform any supported call against your organization and every +application in it, and application-level authentication grants full +permission to perform any supported call against all of the resources in +an application. Should your client id and client secret be compromised, +a malicious user would gain broad access to your organization or +application.

+

To authenticate using client id and secret, append the following +parameters to your request URL:

+
client_id=<your-client-id>&client_secret=<your-client-secret>
+
+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/security-and-auth/authenticating-users-and-application-clients.html b/content/docs/security-and-auth/authenticating-users-and-application-clients.html new file mode 100644 index 0000000000..ef0e3a753f --- /dev/null +++ b/content/docs/security-and-auth/authenticating-users-and-application-clients.html @@ -0,0 +1,544 @@ + + + + + + + + + + + Authenticating users & app clients — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Authenticating users & app clients

+

To protect your Usergrid application data, one of the steps you’ll take +is to authenticate your app’s users. By ensuring that they are who they +say they are, you can help ensure that your application’s data is +available in secure ways. After you’ve created permission rules that +define access to your application and have associated these rules with +users, you’ll want to add code that authenticates your user, as +described in this topic.

+

Note

+

+ + +You manage access to your application's data by creating permission

rules that govern which users can do what. Users authenticated as +Application User have access according to these rules. For more about +managing permissions, see Using +Permissions.

+

+

Authentication levels

+

Usergrid supports four levels of authentication:

+
    +
  • Application user: Grant’s user access to an API Services +application, based on the roles and permissions assigned to the user.
  • +
  • Application client: Grants full access to perform API requests +against an API Services application.
  • +
  • Organization client: Grants full access to perform API requests +against an API Services organization.
  • +
  • Admin user: Grants full access to perform API requests against +any API Services organization that the user is an admin of.
  • +
+

Because the scope of access provided by the application client, +organization client, and admin user authentication levels is so broad +(and as a result, so powerful), it’s a bad practice to use them from a +mobile app or any client-side code. Instead, they’re better suited to +server-side implementations, such as web applications.

+

For a more detailed description of available authentication levels, see +Authentication levels.

+
+
+

Application user authentication (user login)

+

Using the username and password values specified when the user entity +was created, your app can connect to the Usergrid application endpoint +to request an access token. It’s also acceptable to use the user’s email +address in place of the username.

+
+

Using the SDKs

+

When a user is logged in using the Usergrid iOS, JavaScript, node.JS and +Android SDKs, the returned token is automatically stored in the +UsergridDataClient (iOS), DataClient (Android), or Usergrid.Client +(JavaScript/node.JS) class instance, and will be sent to the API with +all subsequent method calls.

+
+

Request syntax

+
curl -X POST "https://api.usergrid.com/<orgName>/<appName>/token" -d '{"grant_type":"password", "username":<username>, "password":<password>}'
+
+
+
+
+

Example request

+
curl -X POST "https://api.usergrid.com/my-org/my-app/token" -d '{"grant_type":"password", "username":"john.doe", "password":"testpw"}'
+
+
+
+
+

Example response

+

The results include the access token needed to make subsequent API +requests on behalf of the application user:

+
{
+"access_token": "5wuGd-lcEeCUBwBQVsAACA:F8zeMOlcEeCUBwBQVsAACA:YXU6AAABMq0hdy4",
+"expires_in": 3600,
+    "user": {
+        ...
+    }
+}
+
+
+
+
+
+
+

Application client authentication

+

Using your app’s client id and client secret values, your app can +connect to the Usergrid application endpoint to request an access token. +The client ID and secret for your app can be found in ‘Getting Started’ +section of the API Services admin portal, under ‘Server App +Credentials’.

+

WARNING

+

+ + +Warning: You should never authenticate this way from a client-side app

such as a mobile app. A hacker could analyze your app and extract the +credentials for malicious use even if those credentials are compiled and +in binary format. See Security Best +Practices for +additional considerations in keeping access to your app and its data +secure.

+

+

Request syntax

+
curl -X POST "https://api.usergrid.com/<orgName>/<appName>/token" -d '{"grant_type":"client_credentials", "client_id":<application_clientID>, "client_secret":"<application_client_secret>"}'
+
+
+
+
+

Example request

+
curl -X POST "https://api.usergrid.com/my-org/my-app/token" -d '{"grant_type":"client_credentials", "client_id":"YXB7NAD7EM0MEeJ989xIxPRxEkQ", "client_secret":"YXB7NAUtV9krhhMr8YCw0QbOZH2pxEf"}'
+
+
+
+
+

Example response

+

The results include the access token needed to make subsequent API +requests on behalf of the application:

+
{
+    "access_token": "F8zeMOlcEeCUBwBQVsAACA:YXA6AAABMq0d4Mep_UgbZA0-sOJRe5yWlkq7JrDCkA",
+    "expires_in": 3600,
+    "application": {
+        ...
+    }
+}
+
+
+
+
+
+

Admin user authentication

+

If you do require admin user access, your app can connect to the +Usergrid management endpoint to request an access token. Your app +supplies the username and password of an admin user in the request.

+

WARNING

+

+ + +Warning: Authenticating as an admin user grants full access to one or

more organizations and all of the applications contained in those +organizations. Due to this, be cautious when implementing this type of +authentication in client-side code. Instead, consider implementing admin +user access in server-side code only. See Security Best +Practices for +additional considerations in keeping access to your app and its data +secure.

+

+

Request syntax

+
curl -X POST "https://api.usergrid.com/management/token" -d '{"grant_type":"password", "username":<admin_username>, "password":<admin_password>}'
+
+
+
+
+

Example Request

+
curl -X POST "https://api.usergrid.com/management/token"  -d '{"grant_type":"password", "username":"testadmin", "password":"testadminpw"}'
+
+
+
+
+

Example response

+

The results include the access token needed to make subsequent API +requests on behalf of the admin user:

+
{
+    "access_token": "f_GUbelXEeCfRgBQVsAACA:YWQ6AAABMqz_xUyYeErOkKjnzN7YQXXlpgmL69fvaA",
+    "expires_in": 3600,
+    "user": {
+        ...
+    }
+}
+
+
+
+
+
+

Organization client authentication

+

If you do require organization level access, your app can connect to the +Usergrid management endpoint to request an access token. Access to an +organization requires the client id and client secret credentials. The +client ID and secret for your organization can be found on the ‘Org +Administration’ page of the API Services admin console under +‘Organization API Credentials’.

+

WARNING

+

+ + +Warning: You should never authenticate this way from a client-side app

such as a mobile app. A hacker could analyze your app and extract the +credentials for malicious use even if those credentials are compiled and +in binary format. See Security Best +Practices for +additional considerations in keeping access to your app and its data +secure.

+

+

Request syntax

+
curl -X POST "https://api.usergrid.com/management/token" -d '{"grant_type":"client_credentials", "client_id":<org_clientID>, "client_secret":<org_client_secret>}'
+
+
+
+
+

Example request

+
curl -X POST "https://api.usergrid.com/management/token" -d '{"grant_type":"client_credentials", "client_id":"YXB7NAD7EM0MEeJ989xIxPRxEkQ", "client_secret":"YXB7NAUtV9krhhMr8YCw0QbOZH2pxEf"}'
+
+
+
+
+

Example response

+

The results include the access token needed to make subsequent API +requests to the organization:

+
{
+    "access_token": "gAuFEOlXEeCfRgBQVsAACA:b3U6AAABMqz-Cn0wtDxxkxmQLgZvTMubcP20FulCZQ",
+    "expires_in": 3600,
+    "organization": {
+        ...
+    }
+}
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/security-and-auth/changing-token-time-live-ttl.html b/content/docs/security-and-auth/changing-token-time-live-ttl.html new file mode 100644 index 0000000000..7fd9c05c26 --- /dev/null +++ b/content/docs/security-and-auth/changing-token-time-live-ttl.html @@ -0,0 +1,403 @@ + + + + + + + + + + + Changing token expiration (time-to-live) — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Changing token expiration (time-to-live)

+

An access token has a “time-to-live” (ttl), which is the maximum time +that the access token will be valid for use within the application. With +the Usergrid, you can change the default ttl for all application user +tokens, set the ttl for an individual token at the time of creation, or +revoke one or more tokens. This gives you a high degree of control over +access to your Usergrid account and data store.

+
+

Default ttl

+

By default, all tokens have a system-defined time-to-live of 7 days +(604800 seconds). Note that Token ttl is specified in milliseconds, but +when a token is created, the API response will return the ttl in +seconds.

+
+
+

Changing the default ttl

+

You can change the default ttl for all application user tokens (that is, +tokens associated with a user entity) by updating the application +entity’s accesstokenttl property. Changing the default ttl will only +affect new tokens. Any existing tokens will not be affected.

+

Please note that this does not apply to application client, organization +client or admin user tokens. For more on obtaining tokens for these +other authorization levels, see Authenticating users and application +clients.

+

Note: If you set ttl=0, the token will never expire. This can pose a +security risk and should be used with caution.

+
+

Request syntax

+
curl -X PUT https://api.usergrid.com/<org_name>/<app_name> -d '{"accesstokenttl":<ttl_in_milliseconds>}'
+
+
+
+
+

Example Request

+
curl -X PUT https://api.usergrid.com/your-org/your-app -d '{"accesstokenttl":"1800000"}'
+
+
+
+
+

Example response

+
{
+  "action" : "put",
+  "application" : "d878de4r-99a7-11e3-b31d-5373d7165c2d",
+  "params" : {
+    "access_token" : [ "DFR4d5M1mJmoEeOGVPncm-g9qgAAAURv_lfQ7uu6aYHjJJn7QCrGoVnvU-ob5Ko" ]
+  },
+  "uri" : "https://api.usergrid.com/amuramoto/secured",
+  "entities" : [ {
+    "uuid" : "d878de4r-99a7-11e3-b31d-5373d7165c2d",
+    "type" : "application",
+    "name" : "your-org/your-app",
+    "created" : 1392843003032,
+    "modified" : 1392843615777,
+    "accesstokenttl" : 1800000,
+    "organizationName" : "your-org",
+    "applicationName" : "your-app",
+    "apigeeMobileConfig" : "{...}",
+    "metadata" : {
+      "collections" : [ "activities", "assets", "devices", "events", "folders", "groups", "roles", "users" ]
+    }
+  } ],
+  "timestamp" : 1392843615767,
+  "duration" : 28,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+
+

Changing ttl when a token is created

+

When you request an access token, you can override its ttl by including +a ttl property in the body of the request when the token is created. +This applies to tokens for all authentication levels, including +application user, admin user, organization client, and application +client authentication levels.

+

The ttl must be equal to or less than the value of the application +entity’s accesstokenttl property. If you specify a ttl value greater +than the value of accesstokenttl, an error message is returned that +indicates the maximum time to live value that can be specified.

+

For example, the following would create an application user token with a +ttl of 180000000 milliseconds:

+
curl -X POST https://api.usergrid.com/your-org/your-app/token -d '{"username":"someUser", "password":"somePassword", "grant_type":"password", "ttl":"180000000"}'
+
+
+

Note: If you set ttl=0, the token will never expire. This can pose a +security risk and should be used with caution.

+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/security-and-auth/facebook-sign.html b/content/docs/security-and-auth/facebook-sign.html new file mode 100644 index 0000000000..c1b144f0b2 --- /dev/null +++ b/content/docs/security-and-auth/facebook-sign.html @@ -0,0 +1,520 @@ + + + + + + + + + + + Facebook sign in — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Facebook sign in

+

You can authenticate your Usergrid requests by logging into Facebook. To +access Usergrid resources, you need to provide an access token with each +request (unless you use the sandbox app). You can get an access token by +connecting to an appropriate web service endpoint and providing the +correct client credentials — this is further described in Authenticating +users and application clients. However, you can also obtain an access +token by logging into Facebook.

+

To enable authentication to Usergrid through Facebook, do the following +in your app:

+
    +
  1. Make a login call to the Facebook API (do this using the Facebook SDK +or API). If the login succeeds, a Facebook access token is returned.
  2. +
  3. Send the Facebook access token to Usergrid. If the Facebook access +token is valid and the user does not already exist in Usergrid, +Usergrid provisions a new Usergrid user. It also returns an Usergrid +access token, which you can use for subsequent Usergrid API calls. +Behind the scenes, Usergrid uses the Facebook access token to +retrieve the user’s profile information from Facebook.
  4. +
  5. If the Facebook access token is invalid, Facebook returns an OAuth +authentication error, and the login does not succeed.
  6. +
+

The request to authenticate to Usergrid using a Facebook access token +is:

+
GET https://api.usergrid.com/{my_org}/{my_app}/auth/facebook?fb_access_token={fb_access_token}
+
+
+

where:

+
    +
  • {my_org} is the organization UUID or organization name.
  • +
  • {my_app} is the application UUID or application name.
  • +
  • {fb_access_token} is the Facebook access token.
  • +
+
+

Facebook login example

+

The Facebook technical guides for login present detailed information on +how to add Facebook login to your app. Instructions are provided for +JavaScript, iOS, and Android.

+

In brief, here are the steps for JavaScript. You can see these steps +implemented in the Facebook login example packaged with the JavaScript +SDK for Usergrid (which you can download in ZIP format or tar.gz +format). The Facebook login example is in the /examples/facebook +directory of the extracted download. The code example snippets shown +below are taken from the Facebook login example.

+
+

Step 1: Create a Facebook app

+

Create a new app on the Facebook App Dashboard. Enter your app’s basic +information. Once created, note the app ID shown at the top of the +dashboard page.

+
+
+

Step 2: Invoke the Facebook OAuth dialog

+

Invoke the Facebook OAuth Dialog. To do that, redirect the user’s +browser to a URL by inserting the following Javascript code after the +opening

+

tag in your app’s HTML file:

+
https://www.facebook.com/dialog/oauth/?
+    client_id={YOUR_APP_ID}
+    &redirect_uri={YOUR_REDIRECT_URL}
+    &state={YOUR_STATE_VALUE}
+    &scope={COMMA_SEPARATED_LIST_OF_PERMISSION_NAMES}
+    &response_type={YOUR_RESPONSE_TYPE}
+
+
+

where:

+

{YOUR_APP_ID} is the app ID. {YOUR_REDIRECT_URL} is the +application UUID or application name. {YOUR_STATE_VALUE} is a unique +string used to maintain application state between the request and +callback. {COMMA_SEPARATED_LIST_OF_PERMISSION_NAMES} is a comma +separated list of permission names which you would like the user to +grant your application. {YOUR_RESPONSE_TYPE}is the requested +response type, either code or token. Defaults to code. Set the response +type to token. With the response type set to token, the Dialog’s +response will include an OAuth user access token in the fragment of the +URL the user is redirected to, as per the client-side authentication +flow.

+

Here is how it’s done in the Facebook login example:

+
var apiKey = $("#api-key").val();
+var location = window.location.protocol + '//' + window.location.host;
+var path = window.location.pathname;
+
+var link = "https://www.facebook.com/dialog/oauth?client_id=";
+link += apiKey;
+link += "&redirect_uri=";
+link += location+path
+link += "&scope&COMMA_SEPARATED_LIST_OF_PERMISSION_NAMES&response_type=token";
+
+//now forward the user to facebook
+window.location = link;
+
+
+

Notice that the response type is set to token. As a result, a Facebook +access token will be appended to the URL to which the user is +redirected.

+
+
+

Step 3: Add the JavaScript SDK for Facebook

+

Add the following Javascript SDK initialization code after the code that +invokes the Facebook OAuth Dialog. The code will load and initialize the +JavaScript SDK in your HTML page. Replace YOUR_APP_ID with the App +ID noted in Step 1, and WWW.YOUR_DOMAIN.COM with your own domain.

+
window.fbAsyncInit = function() {
+    FB.init({
+      appId      : 'YOUR_APP_ID', // App ID
+      channelUrl : '//WWW.YOUR_DOMAIN.COM/channel.html', // Channel File
+      status     : true, // check login status
+      cookie     : true, // enable cookies to allow the server to access the session
+      xfbml      : true  // parse XFBML
+    });
+
+
+

Here is how the window.fbAsynchInit() function is implemented in the +Facebook login example:

+
//load up the facebook api sdk
+  window.fbAsyncInit = function() {
+    FB.init({
+      appId      : '308790195893570', // App ID
+      channelUrl : '//usergridsdk.dev//examples/channel.html', // Channel File
+      status     : true, // check login status
+      cookie     : true, // enable cookies to allow the server to access the session
+      xfbml      : true  // parse XFBML
+    });
+  };
+
+
+
+
+

Step 4. Setup FB.login

+

Whenever a user is either not logged into Facebook or not authorized for +an app, it is useful to prompt them with the relevant dialog. The +FB.login() Javascript SDK function automatically displays the +correct one to the user.

+

To integrate FB.login() function in your existing code:

+
function login() {
+    FB.login(function(response) {
+        if (response.authResponse) {
+            // connected
+        } else {
+            // cancelled
+        }
+    });
+}
+
+
+

Here is how FB.login() is implemented in the Facebook login example:

+
function login(facebookAccessToken) {
+    client.loginFacebook(facebookAccessToken, function(err, response){
+      var output = JSON.stringify(response, null, 2);
+      if (err) {
+        var html = '<pre>Oops!  There was an error logging you in. \r\n\r\n';
+        html += 'Error: \r\n' + output+'</pre>';
+      } else {
+        var html = '<pre>Hurray!  You have been logged in. \r\n\r\n';
+        html += 'Facebook Token: ' + '\r\n' + facebookAccessToken + '\r\n\r\n';
+        html += 'Facebook Profile data stored in Usergrid: \r\n' + output+'</pre>';
+      }
+      $('#facebook-status').html(html);
+    })
+  }
+
+
+

The client.loginFacebook() function is provided by the Usergrid +JavaScript SDK. It uses the Facebook auth token to obtain an Usergrid +auth token. If the Facebook access token is valid and the user does not +already exist in Usergrid, the function creates a user entity for the +user. It also uses the Facebook access token to retrieve the user’s +profile information from Facebook.

+

Here is what the client.loginFacebook() function looks like:

+
Usergrid.Client.prototype.loginFacebook = function (facebookToken, callback) {
+  var self = this;
+  var options = {
+    method:'GET',
+    endpoint:'auth/facebook',
+    qs:{
+      fb_access_token: facebookToken
+    }
+  };
+  this.request(options, function(err, data) {
+    var user = {};
+    if (err && self.logging) {
+      console.log('error trying to log user in');
+    } else {
+      user = new Usergrid.Entity('users', data.user);
+      self.setToken(data.access_token);
+    }
+    if (typeof(callback) === 'function') {
+      callback(err, data, user);
+    }
+  });
+}
+
+
+

Notice that the function also returns an Usergrid access token, which +you can use for subsequent Usergrid API calls.

+

Remember to create a client for your app, which is the main entry point +to the JavaScript SDK for Usergrid. You need to do this before you can +use the SDK. Here’s the code to create a client:

+
var client = new Usergrid.Client({
+    orgName:'yourorgname',
+    appName:'yourappname',
+    logging: true, //optional - turn on logging, off by default
+    buildCurl: true //optional - turn on curl commands, off by default
+});
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/security-and-auth/revoking-tokens-logout.html b/content/docs/security-and-auth/revoking-tokens-logout.html new file mode 100644 index 0000000000..a8ff8c3826 --- /dev/null +++ b/content/docs/security-and-auth/revoking-tokens-logout.html @@ -0,0 +1,356 @@ + + + + + + + + + + + Revoking tokens (logout) — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Revoking tokens (logout)

+

Under certain circumstances, you may need to explicitly revoke one or +more tokens associated with a user entity, such as when a user logs out +of your app. This is accomplished by making a PUT request to the +/revoketoken and /revoketokens endpoints.

+
+

Revoking tokens (user logout)

+

If a user has been logged in using the Usergrid iOS, Android, JavaScript +or node.JS SDKs, the returned token is automatically stored in the +UsergridDataClient (iOS), DataClient (Android), Usergrid.Client +(JavaScript), Usergrid.Client (node.JS) class instance. Calling the +logout method of the SDK will destroy the token on the server, as well +as in the client object.

+
+

Request syntax

+

Revoke all tokens associated with a user entity

+
curl -X PUT https://api.usergrid.com/<org_name>/<app_name>/users/<user_uuid_or_username>/revoketokens
+
+
+

Revoke a specific token associated with a user entity

+
curl -X PUT https://api.usergrid.com/<org_name>/<app_name>/users/<user_uuid_or_username>/revoketoken?token=<token_to_revoke>
+
+
+
+
+

Example request

+
curl -X PUT https://api.usergrid.com/your-org/your-app/users/someUser/revoketokens
+
+
+

Example response

+
{
+  "action" : "revoked user token",
+  "timestamp" : 1382050891455,
+  "duration" : 24
+}
+
+
+
+
+

Revoking admin user tokens

+

The /revoketoken and /revoketokens endpoints also work for revoking +admin user tokens by making a PUT request to /management/users//

+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/security-and-auth/securing-your-app.html b/content/docs/security-and-auth/securing-your-app.html new file mode 100644 index 0000000000..9b6bc2b6c9 --- /dev/null +++ b/content/docs/security-and-auth/securing-your-app.html @@ -0,0 +1,412 @@ + + + + + + + + + + + Security best practices — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Security best practices

+

There a number of actions you should take to ensure that your app is +secure before you put it into production. The following is not an +exhaustive list, but offers some common best practices you should +consider following to keep your app secure when using the Usergrid.

+
+

Never use the ‘sandbox’ for a production app

+

By default, every new Usergrid account has an app named “sandbox” that +is already created under your new organization. This app is no different +than any other app that you might create, except that the Guest role has +been given full permissions (that is, /** for GET, POST, PUT, and +DELETE). This eliminates the need for a token when making application +level calls, and can make it much easier to get your app up and running; +however, it also means that any data in the sandbox application is +completely unsecured.

+

As with any other app, you can secure the sandbox application by +updating its roles and permissions. For more on working with permissions +and roles, see Using Permissions.

+
+
+

Review permissions in your apps

+

Prior to launching your app into a production environment, it is +advisable to review all the roles and permissions you have set up, as +well as the groups and users you have assigned those permissions and +roles to. During development, you may find that you added various +permissions which may or may not still be required once the app is +complete. Review all permissions and delete any that are no longer +required.

+

Prior to taking your app live, you should secure it by removing any +unnecesary Guest permissions. (See Using +Permissions for further information about +setting permissions.) After you secure your the app, any calls to the +API will need to include an OAuth token. Oauth tokens (also called +access tokens) are obtained by the API in response to successful +authentication calls. Your app saves the token and uses it for all +future calls during that session. Learn more about access tokens in +Authenticating users and application clients.

+
+
+

Edit the ‘default’ role

+

When preparing an application for production use, a good first step is +to edit permission rules for the Default role. The permissions in this +role will be applied to every user who authenticates with a valid access +token.

+

For example, in the Default role, you will most likely first want to +remove the permission rule that grants full access to all authenticated +users:

+
GET,PUT,POST,DELETE:/users/me/**
+
+
+

For more on roles, see Using Permissions.

+

Review test accounts If you created any test user or test administrator +accounts during development, these should also be reviewed for relevancy +and security. Delete any test accounts that are no longer needed. If +these accounts are still needed, make sure that passwords have been +secured to the standards required by your app.

+
+
+

Use https

+

Make sure that any calls you make to the API are done using the secure +https protocol, and not the insecure http protocol.

+

If your app is a web app, that is, an app served by a web server, make +sure that the app is served using https.

+
+
+

Acquire access tokens in a secure way

+

There are various methods for acquiring an access token (see +Authenticating users and application +clients. One +method is to use the application or organization level client +secret-client id combination. This method should not be used in client +applications (this is, apps that are deployed to a device, and which +authenticate and make calls against the API).

+

That’s because a hacker could analyze your app (even a compiled, binary +distribution of your app), and retrieve the secret-id combination. Armed +with this information, an attacker could gain full access to the data in +your account.

+

Instead, use application user credentials. This means that your app’s +users should provide a username and password. Your app would use these +to authenticate against the API and retrieve an access token.

+

The client secret-client id combination should be used only in secure, +server-side applications where there is no possibility of a hacker +gaining control of the credentials.

+
+
+

Treat mobile clients as untrustworthy

+

For mobile access, it is recommended that you connect as an application +user with configured access control policies. Mobile applications are +inherently untrusted because they can be easily examined and even +decompiled.

+

Any credentials stored in a mobile app should be considered secure only +to the Application User level. This means that if you don’t want the +user to be able to access or delete data in your Usergrid application, +you need to make sure that you don’t enable that capability through +roles or permissions. Because most web applications talk to the database +using some elevated level of permissions, such as root, it’s generally a +good idea for mobile applications to connect with a more restricted set +of permissions. For more information on restricting access through +permission rules, see Using Permissions.

+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/security-and-auth/user-authentication-types.html b/content/docs/security-and-auth/user-authentication-types.html new file mode 100644 index 0000000000..f2744f5252 --- /dev/null +++ b/content/docs/security-and-auth/user-authentication-types.html @@ -0,0 +1,418 @@ + + + + + + + + + + + Authentication levels — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Authentication levels

+

Usergrid supports four levels of authentication, but only one of them is +used when checking a registered user’s permissions. The other three +levels are useful for authenticating other application or web clients +that require higher-level access to your Usergrid application or +organization. Because the scope of access that the other authentication +levels provide is so broad (and as a result, so powerful), it’s a bad +practice to use them from a mobile app. Instead, they’re better suited +to other client apps, such as web applications.

+
+

Configuring authentication levels

+

Access permissions can only be configured for the ‘application user’ – +this can be done both programmatically and in the admin portal. The +application, organization and admin clients cannot be configured, and +can only be accessed programmatically via the API.

+

For more about creating and managing roles and permissions for +application users, see Using +Permissions and Using +Roles. For a look at how +security features fit together, see App Security +Overview.

+
+
+

User authentication level

+ + + + + + + + + +

Authentication Level

+

Description

+

Application user

+

This is the standard authentication type you will use to implement user +login for your app. The application user level allows access to your +Usergrid application as governed by the permission rules you create and +associated with users and user groups. For more on setting permissions +see Using Permissions. +Each Application User is represented by a User entity in your Usergrid +application. For more about the User entity, see User.

+
+
+

Admin authentication levels

+

WARNING

+

+ + +Warning: Safe use of admin authentication levels. Never use client ID

and client secret, or any hard-coded credentials to authenticate this +way from a client-side app, such as a mobile app. A hacker could analyze +your app and extract the credentials for malicious use even if those +credentials are compiled and in binary format. Even when authenticating +with username and password, be cautious when using these authentication +levels since they grant broad access to your Usergrid account. See +Security Best +Practices for +additional considerations in keeping access to your app and its data +secure.

+

+ + + + + + + + + + + + + + + + + + +

Authentication Level

+

Description

+

Application client

+

Grants full access to perform any operation on an Usergrid application +(but not other applications within the same organization).

+

Authentication at this level is useful in a server-side application (not +a mobile app) that needs access to resources through the Usergrid API. +For example, imagine you created a website that lists every hiking trail +in the Rocky Mountains. You would want anyone to be able to view the +content, but would not want them to access the Usergrid API and all your +data directly. Instead, you would authenticate as an application client +in your server-side code to access the data via the API in order to +serve it to your website’s visitors.

+

Organization client

+

Grants full access to perform any operation on an Usergrid organization.

+

This authentication level provides the greatest amount of access to an +individual organization, allowing a client to perform any operation on +an Usergrid organization and any applications in that organization. This +level of access should be used sparingly and carefully.

+

Admin user

+

Allows full access to perform any operation on all organization accounts +of which the admin user is a member.

+

This authentication level is useful from applications that provide +organization-wide administration features. For example, the Usergrid +admin portal uses this level of access because it requires full access +to the administration features.

+

Unless you have a specific need for administrative features, such as to +run test scripts that require access to management functionality, you +should not use the admin user authentication level.

+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/security-and-auth/using-permissions.html b/content/docs/security-and-auth/using-permissions.html new file mode 100644 index 0000000000..5b30ca481b --- /dev/null +++ b/content/docs/security-and-auth/using-permissions.html @@ -0,0 +1,524 @@ + + + + + + + + + + + Using permissions — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Using permissions

+

Permissions allow you to define user access to perform GET, POST, PUT, +or DELETE operations on specific resources. When the user submits a +request via your app code to the Usergrid API, the user’s permissions +are checked against the resource paths that the user is trying to +access. The request succeeds only if access to the resource is allowed +by the permission rules you specify.

+
+

Permissions syntax

+

In Usergrid, permissions are represented in the following format:

+
<operations>:<resource_path>
+
+
+
    +
  • <operations>: A comma-delimited set of HTTP methods (GET, +PUT, POST, DELETE) that are allowed for the specified +resource path. For example, get, post would allow only +GET and POST requests to be made to the specified resource.
  • +
  • <resource_path>: The path to the resources to be accessed. For +example, /users would apply the permission to the users +collection, while /users/Tom would apply the permission to only +the user entity with username ‘Tom’.
  • +
+
+
+

Complex paths

+

Complex paths can be defined using Apache Ant pattern +syntax. The +following special path variables are supported for the construction of +complex paths:

+ + + + + + + + + + + + + + + + + +

Parameter

+

Description

+

*

+

Treated as a wildcard. Assigns the permission to all paths at the +specified level in the path hierarchy. For example, /* would match +any collection, while /users/Tom/* would match /users/Tom/likes and +/users/Tom/owns.

+

**

+

Assigns the permission to the path recursively. For example, +**/likes would match /likes and /users/likes, while +/users/** would match /users and /users/likes.

+

${user}

+

Automatically sets the path segment to the UUID of the currently +authenticated user. For example, if you sent a request with a valid +access token for a user with UUID +bd397ea1-a71c-3249-8a4c-62fd53c78ce7, the path /users/${user} +would be interpreted as /users/bd397ea1-a71c-3249-8a4c-62fd53c78ce7, +assigning the permission only to that user entity.

+
+
+

Assigning permissions

+

Permissions can only be assigned to user, group or role entities. +Assigning permissions to roles can be particularly useful, as it allows +you to create sets of permissions that represent complex access +definitions, which can then be assigned to user and group entities. For +more on roles, see Using Roles.

+
+

Request syntax

+
curl -X POST https://api.usergrid.com/<org>/<app>/<collection>/<entity>/permissions -d '{"permission":<permissions>}'
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription
orgOrganization UUID or organization name
appApplication UUID or application name
collectionThe collection of the entity that the permissions are to be assigned to.
entityThe UUID of the entity to assign the permissions to. For users, username and for groups, name are also accepted.
permissionsThe permissions to assign to the entity. See Permissions syntax for format.
+

For collections, Valid values are users and groups.

+
+
+

Example request

+

For example, the following cURL request would give the user ‘Tom’ POST +permission to the /users collection:

+
curl -X POST https://api.usergrid.com/your-org/your-app/users/Tom/permissions -d '{"permission":"post:/users"}'
+
+
+
+
+

Example response

+

The newly assigned permission is returned in the data property of the +response:

+
{
+  "action" : "post",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : { },
+  "uri" : "https://api.usergrid.com/your-org/your-app",
+  "entities" : [ ],
+  "data" : [ "post:/users" ],
+  "timestamp" : 1402349612382,
+  "duration" : 19,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+
+

Removing permissions

+

Using a DELETE request, you can remove one of more permissions from a +user, group, or role entity.

+
+

Request syntax

+
curl -X DELETE https://api.usergrid.com/<org>/<app>/<collection>/<entity>/permissions?=<permissions>
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription
orgOrganization UUID or organization name
appApplication UUID or application name
collectionThe collection of the entity that the permissions are to be assigned to. Valid values are users and groups.
entityThe UUID of the entity to assign the permissions to. For users, username and for groups, name are also accepted.
permissionsThe permissions to assign to the entity. See Permissions syntax for format.
+
+
+

Example request

+
curl -X DELETE https://api.usergrid.com/your-org/your-app/users/Tom/permissions?permission=post:/users
+
+
+
+
+

Example response

+

The deleted permission is returned in the params.permission property of +the response:

+
{
+  "action" : "delete",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : {
+    "permission" : [ "post:/users" ]
+  },
+  "uri" : "https://api.usergrid.com/your-org/your-app",
+  "entities" : [ ],
+  "data" : [ "post:/assets" ],
+  "timestamp" : 1402349951530,
+  "duration" : 20,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/security-and-auth/using-roles.html b/content/docs/security-and-auth/using-roles.html new file mode 100644 index 0000000000..16139ac07c --- /dev/null +++ b/content/docs/security-and-auth/using-roles.html @@ -0,0 +1,751 @@ + + + + + + + + + + + Using roles — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Using roles

+

Roles are named sets of one or more permissions, and are useful for +defining specific access levels to resources in your Usergrid data +store. Multiple roles can be assigned to a user or group, giving you a +great deal of flexibility in how access to resources are defined.

+

For example, in a blogging app you might create a ‘reviewer’ role that +allows GET and PUT access to an articles collection to allow the user to +retrieve and update articles, but not allow them to create new articles.

+
+

Default roles

+

While you can create as many custom roles as you want per application, +all Usegrid applications include three default roles. These roles each +serve a special purpose and should not be deleted; however, you can and +should adjust the permissions assigned to these roles to suit the needs +of you app.

+

The following table describes each pre-defined role, and the permissions +that are assigned to them by default.

+ + + + + + + + + + + + + + + + + + + + + +

Role

+

Permissions

+

Description

+

Guest

+
    +
  • post: /devices
  • +
  • post: /users
  • +
  • put: /devices/*
  • +
+

Assigned to all unauthenticated requests. Includes a basic set of +permissions that are commonly needed by unregistered or unauthenticated +users.

+

Grants permission for a user to create a user account and for their +device to be registered.

+

Default

+
    +
  • get, post, put, delete: /**
  • +
+

Default for authenticated users. Assigns the associated permissions to +all users whose requests are authenticated with a valid access token.

+

WARNING

+

+ + +By default, **grants full access for all resources in your

application**. A first task in securing your application should be to +restrict access by redefining this role to narrow the access it +provides. Remove the default full permission rule and add restrictive +permission rules for a production deployment.

+

Administrator

+

None

+

Unused until you associate it with users or groups. By default, includes +no permissions that provide access. Grants no access. Consider this a +blank slate. Add permission rules and associate this role with users and +groups as needed.

+

NOTE

+

+ + +The Administrator role is not the same as an organization

administrator, that is, someone who authenticates as an Admin User. The +Admin User is an implicit user created when you create an organization. +After authenticating, the Admin User has full access to all of the +administration features of the Usergrid API. By comparison, the +Administrator role is simply a role (initially without permissions) that +can be assigned to any user.

+

+
+

Creating roles

+

Generally, it is easiest to a create a role for each access type you +want to enable in your app. You may, however, assign multiple roles to +any user or group entity, so you have the flexibility to define any +schema for applying roles that you like.

+

The following shows how to create a new role and assign permissions to +it.

+
+

Request syntax

+

With cURL requests a role entity is created with a POST request, then +permissions must be assigned to it with a separate request. For more on +assigning permissions with cURL, see Using +Permissions.

+

The following details how to create a new role entity.

+
curl -X POST https://api.usergrid.com/<org>/<app>/roles -d '{"name":<roleName>}'
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription
orgOrganization UUID or organization name
appApplication UUID or application name
roleNameThe name of the role to be created
+
+
+

Example request

+
curl -X POST "https://api.usergrid.com/my-org/my-app/roles/ -d '{"name":"manager"}'
+
+
+
+
+

Example response

+
{
+  "action" : "post",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : { },
+  "path" : "/roles",
+  "uri" : "https://api.usergrid.com/your-org/your-app/roles",
+  "entities" : [ {
+    "uuid" : "382d0991-74bb-3548-8166-6b07e44495ef",
+    "type" : "role",
+    "name" : "manager",
+    "created" : 1402612783104,
+    "modified" : 1402612783104,
+    "roleName" : "manager",
+    "title" : "manager",
+    "inactivity" : 0,
+    "metadata" : {
+      "path" : "/roles/382d0991-74bb-3548-8166-6b07e44495ef",
+      "sets" : {
+        "permissions" : "/roles/382d0991-74bb-3548-8166-6b07e44495ef/permissions"
+      },
+      "collections" : {
+        "groups" : "/roles/382d0991-74bb-3548-8166-6b07e44495ef/groups",
+        "users" : "/roles/382d0991-74bb-3548-8166-6b07e44495ef/users"
+      }
+    }
+  } ],
+  "timestamp" : 1402612783102,
+  "duration" : 30,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+

Creating Roles in the Admin Portal

+
    +
  1. In the left sidebar of the Usergrid portal, click Users > Roles. This +displays the roles defined for the application. Click the ‘+’ button.
  2. +
  3. In the dialog box, provide a ‘title’ and ‘role name.’ A title is an +alias for the role name.
  4. +
  5. Click ‘Create’. The role will be created, but will not have any +permissions assigned to it.
  6. +
  7. Click the role you created in the list.
  8. +
  9. Click the ‘Add permissions’ button.
  10. +
  11. In the dialog box, click the check boxes for the HTTP methods you +want to grant permissions for, and enter the resource path in the +‘Path’ field.
  12. +
  13. The ‘Inactivity’ field lets you control automatic user logout during +periods of inactivity. Set a number of seconds of inactivity before +users assigned to this role are automatically logged out.
  14. +
+
+
+
+

Assigning roles

+

Once you have created some roles, you will need to explicitly assign +them to a user or group entity. The permissions associated with that +role will be granted to the entity immediately for any requests they +send that are authenticated by a valid access token. Please note that +assigning a role to a group will grant the associated permissions to +every user in that group.

+

The following shows how to assign a role to an entity.

+
+

Request syntax

+
curl -X POST https://api.usergrid.com/<org>/<app>/roles/<roleName>/<entityType>/<entityID>
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription
orgOrganization UUID or organization name
appApplication UUID or application name
roleNameThe name of the role to be created
entityTypeThe type of the entity the role is being assigned to. ‘Group’ and ‘user’ are valid values.
entityIDThe UUID of the entity the role is being assigned to.
+

For groups, the ‘name’ property can be used. For users, the ‘username’ +property can be used.

+
+
+

Example request

+
curl -X POST "https://api.usergrid.com/my-org/my-app/roles/manager/users/someUser
+
+
+
+
+

Example response

+
{
+  "action" : "post",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : { },
+  "path" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users",
+  "uri" : "https://api.usergrid.com/your-org/your-app/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users",
+  "entities" : [ {
+    "uuid" : "410b213a-b379-11e3-a0e5-9953085ea376",
+    "type" : "user",
+    "name" : "someUser",
+    "created" : 1395681911491,
+    "modified" : 1399070010291,
+    "username" : "someUser",
+    "activated" : true,
+    "file" : "fobnszewobnioerabnoiawegbrn\n",
+    "metadata" : {
+      "connecting" : {
+        "friends" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/connecting/friends",
+        "likes" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/connecting/likes"
+      },
+      "path" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376",
+      "sets" : {
+        "rolenames" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/roles",
+        "permissions" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/permissions"
+      },
+      "connections" : {
+        "completed" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/completed",
+        "follows" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/follows"
+      },
+      "collections" : {
+        "activities" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/activities",
+        "devices" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/devices",
+        "feed" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/feed",
+        "groups" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/groups",
+        "roles" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/roles",
+        "following" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/following",
+        "followers" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/followers"
+      }
+    }
+  } ],
+  "timestamp" : 1402965083889,
+  "duration" : 41,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+

Assigning Roles in the Admin Portal

+

The easiest way to assign roles to user or group entities is to use the +‘Users’ tab of the Usergrid admin portal, by doing the following:

+
    +
  1. In the left sidebar of the admin portal, click Users > Users or Users +> Groups to display either the list of users or groups in your +application.
  2. +
  3. In the list, click the name of the user or group entity you want to +assign roles to to display its details in the right pane.
  4. +
  5. Click the ‘Roles & Permissions’ tab above the right pane.
  6. +
  7. Click the ‘Add Role’ button.
  8. +
  9. In the popup, select a role from the drop down menu.
  10. +
  11. Click the ‘Add’ button.
  12. +
+
+
+
+

Removing roles

+

At times it may be necessary to remove a role from a user or group +entity, for example if a user changes jobs, or the duties of a group are +altered. Please note that removing a role from a group will remove the +associated permissions from every user in that group.

+

The following shows how to remove a role from an entity.

+
+

Request syntax

+
curl -X DELETE https://api.usergrid.com/<org>/<app>/roles/<roleName>/<entityType>/<entityID>
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription
orgOrganization UUID or organization name
appApplication UUID or application name
roleNameThe name of the role to be created
entityTypeThe type of the entity the role is being removed from. ‘Group’ and ‘user’ are valid values.
entityIDThe UUID of the entity the role is being removed from.
+

For groups, the ‘name’ property can be used. For users, the ‘username’ +property can be used.

+
+
+

Example request

+
curl -X DELETE https://api.usergrid.com/my-org/my-app/roles/manager/users/someUser
+
+
+
+
+

Example response

+
{
+  "action" : "delete",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : { },
+  "path" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users",
+  "uri" : "https://api.usergrid.com/your-org/your-app/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users",
+  "entities" : [ {
+    "uuid" : "410b213a-b379-11e3-a0e5-9953085ea376",
+    "type" : "user",
+    "name" : "someUser",
+    "created" : 1395681911491,
+    "modified" : 1399070010291,
+    "username" : "someUser",
+    "activated" : true,
+    "metadata" : {
+      "connecting" : {
+        "friends" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/connecting/friends",
+        "likes" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/connecting/likes"
+      },
+      "path" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376",
+      "sets" : {
+        "rolenames" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/roles",
+        "permissions" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/permissions"
+      },
+      "connections" : {
+        "completed" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/completed",
+        "follows" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/follows"
+      },
+      "collections" : {
+        "activities" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/activities",
+        "devices" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/devices",
+        "feed" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/feed",
+        "groups" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/groups",
+        "roles" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/roles",
+        "following" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/following",
+        "followers" : "/roles/348388de-a5c5-3c1e-9de5-9efc8ad529d8/users/410b213a-b379-11e3-a0e5-9953085ea376/followers"
+      }
+    }
+  } ],
+  "timestamp" : 1403214283808,
+  "duration" : 358,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+

Removing Roles in the Admin Portal

+

The easiest way to remove roles from user or group entities is to use +the ‘Users’ tab of the Usergrid admin portal, by doing the following:

+
    +
  1. In the left sidebar of the Usergrid admin portal, click Users > Users +or Users > Groups to display either the list of users or groups in +your application.
  2. +
  3. In the list, click the name of the user or group entity you want to +remove roles from to display its details in the right pane.
  4. +
  5. Click the ‘Roles & Permissions’ tab above the right pane.
  6. +
  7. Click the role you created in the list.
  8. +
  9. Under ‘Roles’, click the checkbox beside the role you want to remove +from the entity.
  10. +
  11. Click the ‘Leave roles’ button.
  12. +
+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/user-management/activity.html b/content/docs/user-management/activity.html new file mode 100644 index 0000000000..4f457b3385 --- /dev/null +++ b/content/docs/user-management/activity.html @@ -0,0 +1,880 @@ + + + + + + + + + + + Activity — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Activity

+

Most modern applications struggle to manage data streams, such as those +that contain an ongoing list of comments, activities, and tweets. In +particular, mobile applications are prone to generating very large +amounts of data in a data stream. Beyond that, additions to a data +stream must often be routed automatically to subscribers or filtered or +counted.

+

Usergrid provides an activity entity that is specifically designed for +data streams. An activity is an entity type that represents activity +stream actions (see the JSON Activity Streams 1.0 +specification for more +information about these actions).

+

When a user creates an activity, it creates a relationship between the +activity and the user who created it. Because this relationship exists, +the activity will appear in the feed of any of the user’s followers. +Think of the Activities endpoint (/users/{uuid|username}/activities) +as an “outbox” of news items created by the user. Think of the Feed +endpoint (/users/{uuid|username}/feed) as an “inbox” of news items +meant to be seen or consumed by the user.

+

A user can also post an activity to a group (located at +/groups/{uuid|groupname}/activities). This allows you to emulate +Facebook-style group functionality, where a limited number of users can +share content on a common “wall”. In any of these cases, there is no +need to construct publish/subscribe relationships manually.

+

Activity entities are particularly useful in applications that enable +users to post content to activity streams (also called feeds) and to +display activity streams. Some examples of these applications are +Twitter, foursquare, and Pinterest. For example, when a Twitter user +posts a short, 140-character or less, “tweet”, that activity gets added +to the user’s activity stream for display as well as to the activity +streams of any of the user’s followers.

+

Using Usergrid APIs you can create, retrieve, update, and delete +activity entities.

+

Note: Although not shown in the API examples below, you need to +provide a valid access token with each API call. See Authenticating +users and application +clients +for details.

+
+

Posting activities

+

Posting a user activity

+

Use the POST method to create an activity in the activities collection.

+
+

Request URI

+
POST /<org_id>/<app_id>/users/<uuid | username>/activities { request body }
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription
arg uuid|string org_idOrganization UUID or organization name
arg uuid|string app_idApplication UUID or application name
request bodyOne or more sets of activity properties
+

Here’s an example request body:

+
{
+    "actor":{
+        "displayName":"John Doe",
+        "uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1",
+        "username":"john.doe",
+        "image":{
+            "duration":0,
+            "height":80,
+            "url":"http://www.gravatar.com/avatar/","width":80},
+            "email":"john.doe@gmail.com"
+        },
+        "verb":"post",
+        "content":"Hello World!"
+    }
+}
+
+
+
+
+

Example - Request

+
curl -X POST "https://api.usergrid.com/my-org/my-app/users/john.doe/activities" -d '{"actor":{"displayName":"John Doe","uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1","username":"john.doe", "image":{"duration":0,"height":80,"url":"http://www.gravatar.com/avatar/","width":80}, "email":"john.doe@gmail.com"},"verb":"post","content":"Hello World!"}'
+
+
+
+
+

Example - Response

+
{
+    "action" : "post",
+    "application" : "5111c463-6a42-11e1-b6dd-1231380a0284",
+     "params" : {
+    },
+    "path" : "/users/1f3567aa-da83-11e1-afad-12313b01d5c1/activities",
+    "uri" : "https://api.usergrid.com/5111c463-6a42-11e1-b6dd-1231380a0284/users/1f3567aa-da83-11e1-afad-12313b01d5c1/activities",
+    "entities" : [ {
+        "uuid" : "da448955-f3aa-11e1-8042-12313d331ae8",
+        "type" : "activity",
+        "created" : 1346445092974,
+        "modified" : 1346445092974,
+        "actor" : {
+            "displayName" : "John Doe",
+            "uuid" : "1f3567aa-da83-11e1-afad-12313b01d5c1",
+            "username" : "john.doe",
+            "image" : {
+                "duration" : 0,
+                "height" : 80,
+                "url" : "http://www.gravatar.com/avatar/",
+                "width" : 80
+            },
+            "email" : "john.doe@gmail.com"
+        },
+        "content" : "Hello World!",
+        "metadata" : {
+            "path" : "/users/1f3567aa-da83-11e1-afad-12313b01d5c1/activities/da448955-f3aa-11e1-8042-12313d331ae8"
+        },
+        "published" : 1346445092974,
+        "verb" : "post"
+    } ],
+    "timestamp" : 1346445092827,
+    "duration" : 1406,
+    "organization": "my-org",
+    "applicationName": "my-app"
+}
+
+
+

Note: Anytime a logged-in user makes a request, you can substitute +“me” for the uuid or username. So the format of a request to create an +activity for the currently logged-in user would look like this:

+
POST /<org_id>/<app_id>/users/me/activities { request body }
+
+
+

The /users/me endpoint is accessible only if you provide an access +token with the request. If you don’t provide an access token with the +request, that is, you make an anonymous (or “guest”) call, the system +will not be able to determine which user to return as /users/me.

+

When you create an activity it creates a relationship between the +activity and the user who created it. In other words, the newly created +activity above belongs to john.doe. Another way of saying this is the +user “owns” the activity. And because this relationship exists, the +activity will appear in the feed of any of the user’s followers (in this +example, anyone who is following john.doe). However, it will not appear +in the feed of people the user follows. The activity is accessible at +the /activities endpoint to users who have the permission to read +that endpoint.

+

Notice the properties specified in the request body in the previous +example are actor, verb, and content. The actor, verb, and content +properties are built into the Activity entity (see Activity entity +properties ). The actor +property specifies properties of the entity that performs the action +(here, user john.doe). The gravatar URL is used to create an icon for +the activity. And because an Activity is simply an API Services data +entity, you can also create custom properties.

+

The verb parameter is descriptive. You can use it to indicate what type +of activity is posted, for example, an image versus text. The value post +is defined in the JSON Activity Streams specification as “the act of +authoring an object and then publishing it online.“

+
+
+
+

Posting an activity to a group

+

Use the POST method to post an activity to a specific group. In this +case the activity is created in the activities collection and is +accessible at the /activities endpoint to users who have the +permission to read that endpoint. In addition, a relationship is +established between the activity and the group, and because of that, the +activity will appear in the group’s feed. The group “owns” the activity. +Also, the activity will be published in the feed of all users that are +members of the group.

+
+

Request URI

+
POST /{org_id}/{app_id}/groups/{uuid|groupname}/activities {request body}
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + + + + +
ParameterDescription
arg uuid|string org_idOrganization UUID or organization name
arg uuid|string app_idApplication UUID or application name
arg uuid|string groupnameUUID or name of the group
request bodyOne or more sets of activity properties.
+

Here’s a sample request body:

+
{
+  "actor":
+    {
+    "displayName":"John Doe",
+    "uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1",
+    "username":"john.doe",
+    "image":{
+      "duration":0,
+      "height":80,
+      "url":"http://www.gravatar.com/avatar/","width":80},
+  "email":"john.doe@gmail.com"},
+  "verb":"post",
+  "content":"Hello World!"
+}
+
+
+
+
+

Example - Request

+
curl -X POST "https://api.usergrid.com/my-org/my-app/groups/mygroup/activities" -d '{"actor":{"displayName":"John Doe","uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1","username":"john.doe", "image":{"duration":0,"height":80,"url":"http://www.gravatar.com/avatar/","width":80}, "email":"john.doe@gmail.com"},"verb":"post","content":"Hello World!"}'
+
+
+

Because this relationship exists, this activity will appear in the feed +of all users who are members of mygroup. It won’t appear in the feeds of +the group members’ followers or in feeds of users they follow.

+
+
+

Example - Response

+
{
+  "action": "post",
+  "application": "3400ba10-cd0c-11e1-bcf7-12313d1c4491",
+  "params":  {},
+  "path": "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/activities",
+  "uri": "https://api.usergrid.com/my-org/my-app/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/activities",
+  "entities":  [
+     {
+      "uuid": "563f5d96-37f3-11e2-a0f7-02e81ae640dc",
+      "type": "activity",
+      "created": 1353952903811,
+      "modified": 1353952903811,
+      "actor":  {
+        "displayName": "John Doe",
+        "uuid": "1f3567aa-da83-11e1-afad-12313b01d5c1",
+        "username": "john.doe",
+        "image":  {
+          "duration": 0,
+          "height": 80,
+          "url": "http://www.gravatar.com/avatar/",
+          "width": 80
+        },
+        "email": "john.doe@gmail.com"
+      },
+      "content": "Hello World!",
+      "metadata":  {
+        "path": "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/activities/563f5d96-37f3-11e2-a0f7-02e81ae640dc"
+      },
+      "published": 1353952903811,
+      "verb": "post"
+    }
+  ],
+  "timestamp": 1353952903800,
+  "duration": 81,
+  "organization": "my-org",
+  "applicationName": "my-app"
+}
+
+
+
+
+
+

Creating an activity for a user’s followers in a group

+

Use the POST method to create an activity that will be published only in +the feeds of users who (1) follow you, and (2) are in the same group to +which you posted the activity. This is useful if you want to create +specific groups of friends (for example, acquaintances or colleagues) +and publish content to them with more precise privacy settings. This +allows you to re-create a privacy model similar to Google+’s Circles or +Facebook current privacy system.

+

When you create an activity for a user’s followers in a group:

+

The activity is accessible at the /activities endpoint to users who +have the permission to read that endpoint. The activity will not be +cross-posted to the group’s activity endpoint +(/groups/{uuid|groupname}/activities) A relationship is +automatically created between the activity entity that was just created +and the user within that group +(/groups/{uuid|groupname}/users/{uuid|username}) The user within the +group (/groups/{uuid|groupname}/users/{uuid|username}) becomes the +owner of the activity (through the owner property in the activity).

+
+

Request URI

+
POST /{org_id}/{app_id}/groups/{uuid|groupname}/users/{uuid|username}/activities {request body}
+
+
+

Parameters

+

Parameter Description arg uuid|string org_id Organization UUID or +organization name arg uuid|string app_id Application UUID or +application name arg uuid|string groupname UUID or name of the group +arg uuid|string username UUID or name of the user request body One or +more sets of activity properties

+

Example request body:

+
{
+  "actor":
+    {
+    "displayName":"John Doe",
+    "uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1",
+    "username":"john.doe",
+    "image":{
+      "duration":0,
+      "height":80,
+      "url":"http://www.gravatar.com/avatar/","width":80},
+  "email":"john.doe@gmail.com"},
+  "verb":"post",
+  "content":"Hello World!"
+}
+
+
+
+
+

Example - Request

+
curl -X POST "https://api.usergrid.com/my-org/my-app/groups/mygroup/users/john.doe/activities" -d '{"actor":{"displayName":"John Doe","uuid":"1f3567aa-da83-11e1-afad-12313b01d5c1","username":"john.doe", "image":{"duration":0,"height":80,"url":"http://www.gravatar.com/avatar/","width":80}, "email":"john.doe@gmail.com"},"verb":"post","content":"Hello World!"}'
+
+
+

Because this relationship exists, this activity will appear in the feed +of all users who are members of mygroup. It won’t appear in the feeds of +the group members’ followers or in feeds of users they follow.

+
+
+

Example - Response

+
{
+  "action" : "post",
+  "application" : "3400ba10-cd0c-11e1-bcf7-12313d1c4491",
+  "params" : { },
+  "path" : "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/users/34e26bc9-2d00-11e2-a065-02e81ae640dc/activities",
+  "uri" : "https://api.usergrid.com/my-org/my-app/
+/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/users/34e26bc9-2d00-11e2-a065-02e81ae640dc/activities",
+  "entities" : [ {
+    "uuid" : "2440ca58-49ff-11e2-84c0-02e81adcf3d0",
+    "type" : "activity",
+    "created" : 1355937094825,
+    "modified" : 1355937094825,
+    "actor" : {
+      "displayName" : "John Doe",
+      "uuid" : "1f3567aa-da83-11e1-afad-12313b01d5c1",
+      "username" : "john.doe",
+      "image" : {
+        "duration" : 0,
+        "height" : 80,
+        "url" : "http://www.gravatar.com/avatar/",
+        "width" : 80
+      },
+      "email" : "john.doe@gmail.com"
+    },
+    "content" : "Happy New Year!",
+    "metadata" : {
+      "path" : "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/users/34e26bc9-2d00-11e2-a065-02e81ae640dc/activities/2440ca58-49ff-11e2-84c0-02e81adcf3d0"
+    },
+    "published" : 1355937094825,
+    "verb" : "post"
+  } ],
+  "timestamp" : 1355937094789,
+  "duration" : 95,
+  "organization" : "my-org",
+  "applicationName" : "my-app"
+}
+
+
+
+
+
+

Retrieving activity feeds

+

Retrieving a user’s activity feed

+

Use the GET method to retrieve a user’s feed.

+
+

Request URI

+
GET /{org_id}/{app_id}/users/{uuid|username}/feed
+
+
+
+
+

Example - Request

+
curl -X GET "https://api.usergrid.com/my-org/my-app/users/john.doe/feed"
+
+
+
+
+

Example - Response

+
{
+  "action" : "get",
+  "application" : "3400ba10-cd0c-11e1-bcf7-12313d1c44914",
+  "params" : {},
+  "path" : "/users/d9693ec3-61c9-11e2-9ffc-02e81adcf3d0/feed",
+  "uri" : "https://api.usergrid.com/3400ba10-cd0c-11e1-bcf7-12313d1c44914/users/d9693ec3-61c9-11e2-9ffc-02e81adcf3d0/feed",
+  "entities" : [ {
+    "uuid" : "ffd79647-f399-11e1-aec3-12313b06ae01",
+    "type" : "activity",
+    "created" : 1346437854569,
+    "modified" : 1346437854569,
+    "actor" : {
+      "displayName" : "John Doe",
+      "image" : {
+        "duration" : 0,
+        "height" : 80,
+        "url" : "http://www.gravatar.com/avatar/",
+        "width" : 80
+      },
+      "uuid" : "d9693ec3-61c9-11e2-9ffc-02e81adcf3d0",
+      "email" : "john.doe@gmail.com",
+      "username" : "john.doe"
+    },
+    "content" : "Hello World!",
+    "metadata" : {
+      "cursor" : "gGkAAQMAgGkABgE5ffM1aQCAdQAQ_9eWR_OZEeGuwxIxOwauAQCAdQAQABlaOvOaEeGuwxIxOwauAQA",
+      "path" : "/users/d9693ec3-61c9-11e2-9ffc-02e81adcf3d0/feed/ffd79647-f399-11e1-aec3-12313b06ae01"
+    },
+    "published" : 1346437854569,
+    "verb" : "post"
+  }, {
+    "uuid" : "2482a1c5-e7d0-11e1-96f6-12313b06d112",
+    "type" : "activity",
+    "created" : 1345141694958,
+    "modified" : 1345141694958,
+    "actor" : {
+      "displayName" : "moab",
+      "image" : {
+        "duration" : 0,
+        "height" : 80,
+        "url" : "http://www.gravatar.com/avatar/",
+        "width" : 80
+      },
+      "uuid" : "d9693ec3-61c9-11e2-9ffc-02e81adcf3d0",
+      "email" : "massoddb@mfdsadfdsaoabl.com",
+      "username" : "moab"
+    },
+    "content" : "checking in code left and right!!",
+    "metadata" : {
+      "cursor" : "gGkAAQMAgGkABgE5MLFh7gCAdQAQJIKhxefQEeGW9hIxOwbREgCAdQAQJNEP6ufQEeGW9hIxOwbREgA",
+      "path" : "/users/d9693ec3-61c9-11e2-9ffc-02e81adcf3d0/feed/2482a1c5-e7d0-11e1-96f6-12313b06d112"
+    },
+    "published" : 1345141694958,
+    "verb" : "post"
+  } ],
+  "timestamp" : 1346438331316,
+  "duration" : 144,
+  "organization": "my-org",
+  "applicationName": "my-app"
+}
+
+
+
+
+
+

Retrieving a group’s activity feed

+

Use the GET method to retrieve the feed for a group. This gets a list of +all the activities that have been posted to this group, that is, the +activities for which this group has a relationship (owns).

+
+

Request URI

+
GET /{org_id}/{app_id}/groups/{uuid|groupname}/feed
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription
arg uuid|string org_id Organization UUID or organization name
arg uuid|string app_id Application UUID or application name
arg uuid|string groupname UUID or name of the group
+
+
+

Example - Request

+
curl -X GET "https://api.usergrid.com/my-org/my-app/groups/mygroup/feed"
+
+
+
+
+

Example - Response

+
{
+    "action": "get",
+    "application": "3400ba10-cd0c-11e1-bcf7-12313d1c4491",
+    "params":  {},
+    "path": "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/feed",
+    "uri": "https://api.usergrid.com/my-org/my-app/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/feed",
+    "entities":  [
+       {
+        "uuid": "563f5d96-37f3-11e2-a0f7-02e81ae640dc",
+        "type": "activity",
+        "created": 1353952903811,
+        "modified": 1353952903811,
+        "actor":  {
+          "displayName": "John Doe",
+          "image":  {
+            "duration": 0,
+            "height": 80,
+            "url": "http://www.gravatar.com/avatar/",
+            "width": 80
+          },
+          "uuid": "1f3567aa-da83-11e1-afad-12313b01d5c1",
+          "email": "john.doe@gmail.com",
+        "username": "john.doe"
+        },
+        "content": "Hello World!",
+        "metadata":  {
+          "cursor": "gGkAAQMAgGkABgE7PeHCgwCAdQAQVj9dljfzEeKg9wLoGuZA3ACAdQAQVkVRCTfzEeKg9wLoGuZA3AA",
+          "path": "/groups/d87edec7-fc4d-11e1-9917-12313d1520f1/feed/563f5d96-37f3-11e2-a0f7-02e81ae640dc"
+        },
+        "published": 1353952903811,
+        "verb": "post"
+      }
+    ],
+  "timestamp": 1353953272756,
+  "duration": 29,
+  "organization": "my-org",
+  "applicationName": "my-app"
+}
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/user-management/group.html b/content/docs/user-management/group.html new file mode 100644 index 0000000000..a5270a0ed3 --- /dev/null +++ b/content/docs/user-management/group.html @@ -0,0 +1,843 @@ + + + + + + + + + + + Working with group data — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Working with group data

+

You can organize app users into groups. Groups have their own Activity +Feed, their own permissions and be a useful alternative to Roles, +depending on how you model your data. Groups were originally designed to +emulate Facebook Groups, so they will tend to function about the same +way Facebook Groups would.

+

Groups are hierarchical. Every member of the group +/groups/california/san-francisco is also a member of the group +/groups/california.

+

Groups are also a great way to model things such a topic subscriptions. +For example, you could allow people to subscribe (i.e. become a member +of the group and be alerted via Activities) to +/groups/memes/dogs/doge or subscribe to all /groups/memes/dogs.

+

See the Group Model section of the API +Reference for a list of the +system-defined properties for group entities. In addition, you can +create group properties specific to your application.

+
+

Creating groups

+

A group entity represents an application group of users. You can create, +retrieve, update, delete, and query group entities. See User entity +properties for a list of the +system-defined properties for group entities. In addition, you can +create group properties specific to your application.

+
+

Request Syntax

+
curl -X POST "https://api.usergrid.com/your-org/your-app/groups" '{ request body }'
+
+
+

Use the POST method to create a new group. Groups use paths to indicate +their unique names. This allows you to create group hierarchies by using +slashes. For this reason, you need to specify a path property for a new +group.

+
+
+

Request URI

+
POST /{org_id}/{app_id}/groups
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription
uuid | org_idOrganization UUID or organization name
uuid | app_idApplication UUID or application name
request bodyOne or more sets of group properties of which path is mandatory.
+

The path property is required and must be unique, it may include +forward slashes to denote hierarchical relationships.

+
{
+    "path" : "somegroup/somesubgroup",
+    "title" : "Some SubGroup"
+}
+
+
+
+
+

Example

+

Note: Although not shown in the API examples below, you need to +provide a valid access token with each API call. See Authenticating +users and application +clients +for details.

+
+
+

Request

+
curl -X POST "https://api.usergrid.com/my-org/my-app/groups" -d '{"path":"mynewgroup"}'
+
+
+
+
+

Response

+
{
+    "action": "post",
+    "application": "7fb8d891-477d-11e1-b2bd-22000a1c4e22",
+    "params": {},
+    "path": "/groups",
+    "uri": "https://api.usergrid.com/22000a1c4e22-7fb8d891-477d-11e1-b2bd/7fb8d891-477d-11e1-b2bd-22000a1c4e22/groups",
+    "entities": [{
+        "uuid": "a668717b-67cb-11e1-8223-12313d14bde7",
+        "type": "group",
+        "created": 1331066016571,
+        "modified": 1331066016571,
+        "metadata": {
+            "path": "/groups/a668717b-67cb-11e1-8223-12313d14bde7",
+            "sets": {
+                "rolenames": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/rolenames",
+                "permissions": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/permissions"
+            },
+            "collections": {
+                "activities": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/activities",
+                "feed": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/feed",
+                "roles": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/roles",
+                "users": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users"
+            }
+        },
+        "path": "mynewgroup"
+    }],
+    "timestamp": 1331066016563,
+    "duration": 35,
+    "organization": "my-org",
+    "applicationName": "my-app"
+}
+
+
+
+
+
+

Retrieving groups

+

Retrieving group data

+

You can retrieve data about groups through cURL or one of the SDKs. Each +provides a way to filter the list of groups by data associated with the +group, such as title or path, or other properties in the group entity.

+

See the Group Model section of the API +Reference for a list of the +system-defined properties for group entities. In addition, you can +create group properties specific to your application.

+
+

Request Syntax

+
curl -X GET "https://api.usergrid.com/my-org/my-app/groups/mynewgroup"
+
+
+

Use the GET method to retrieve group data.

+
+
+

Request URI

+
GET /<org_id | uuid>/<app_id | uuid>/groups</groupPath | uuid> | <?ql=query_string>
+
+
+

Parameters

+
+
+
+

Parameter Description

+

org_id | uuid Organization UUID or organization name app_id | uuid +Application UUID or application name groupPath | uuid Group UUID or +group path, which must be unique. query_string A data store query. For +more on queries, see Data +queries.

+
+

Request

+
# Get a group by the group path, "employees/managers".
+curl -X GET "https://api.usergrid.com/my-org/my-app/groups/employees/managers"
+
+# Get a group by UUID.
+curl -X GET "https://api.usergrid.com/my-org/my-app/groups/a407b1e7-58e8-11e1-ac46-22000a1c5a67e"
+
+# Get group data filtering by their title.
+curl -X GET "https://api.usergrid.com/my-org/my-app/groups?ql=select%20*%20where%20title%3D'Management%20Employees'"
+
+
+
+
+

Response

+

The following is an example of JSON returned by a query for a single +group.

+
{
+    "action" : "get",
+    "application" : "db1e60a0-417f-11e3-9586-0f1ff3650d20",
+    "params" : { },
+    "path" : "/groups",
+    "uri" : "https://api.usergrid.com/steventraut/mynewapp/groups",
+    "entities" : [ {
+        "uuid" : "5005a0fa-6916-11e3-9c1b-b77ec8addc0d",
+        "type" : "group",
+        "created" : 1387503030399,
+        "modified" : 1387503030399,
+        "path" : "managers",
+        "metadata" : {
+            "path" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d",
+            "sets" : {
+                "rolenames" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/roles",
+                "permissions" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/permissions"
+            },
+            "collections" : {
+                "activities" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/activities",
+                "feed" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/feed",
+                "roles" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/roles",
+                "users" : "/groups/5005a0fa-6916-11e3-9c1b-b77ec8addc0d/users"
+            }
+        },
+        "title" : "Management Employees"
+    } ],
+    "timestamp" : 1391020491701,
+    "duration" : 15,
+    "organization" : "my-org",
+    "applicationName" : "my-app"
+}
+
+
+
+
+
+

Retrieving a group’s users

+

Use the GET method to retrieve all the users in a group.

+
+

Request URI

+
GET /{org_id}/{app_id}/groups/{uuid|groupname}/users
+
+
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription
arg uuid|string org_idOrganization UUID or organization name
arg uuid|string app_idApplication UUID or application name
arg uuid|string groupnameUUID or name of the group
+
+
+

Example - Request

+
curl -X GET "https://api.usergrid.com/my-org/my-app/groups/mygroup/users"
+
+
+
+
+

Example - Response

+
{
+  "action" : "get",
+  "application" : "e7127751-6985-11e2-8078-02e81aeb2129",
+  "params" : { },
+  "path" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users",
+  "uri" : "http://api.usergrid.com/myorg/sandbox/groups/d20976ff-802f-11e2-b690-02e81ae61238/users",
+  "entities" : [ {
+    "uuid" : "cd789b00-698b-11e2-a6e3-02e81ae236e9",
+    "type" : "user",
+    "name" : "barney",
+    "created" : 1359405994314,
+    "modified" : 1361894320470,
+    "activated" : true,
+    "email" : "barney@apigee.com",
+    "metadata" : {
+      "path" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9",
+      "sets" : {
+        "rolenames" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/rolenames",
+        "permissions" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/permissions"
+      },
+      "collections" : {
+        "activities" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/activities",
+        "devices" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/devices",
+        "feed" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/feed",
+        "groups" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/groups",
+        "roles" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/roles",
+        "following" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/following",
+        "followers" : "/groups/d20976ff-802f-11e2-b690-02e81ae66238/users/cd789b00-698b-11e2-a6e3-02e81aeb26e9/followers"
+      }
+    },
+    "name" : "barney",
+    "picture" : "http://www.gravatar.com/avatar/00767101f6b4f2cf5d02ed510dbcf0b4",
+    "test" : "fred",
+    "username" : "barney"
+  } ],
+  "timestamp" : 1361903248398,
+  "duration" : 24,
+  "organization" : "myorg",
+  "applicationName" : "sandbox"
+}
+
+
+
+
+
+

Deleting a group

+

To delete a group, delete the associated group entity as you would any +other entity. Note that this will only delete the group. Any entities in +the group will be preserved.

+

For more information and code samples, see Deleting Data +Entities.

+
+
+

Adding a user to a group

+

You can add users to groups from client code using cURL commands or one +of the SDKs, as described here.

+

When setting up your application on the server, you might find it easier +and more convenient to create and populate groups with the admin portal. +There, you can create groups, create roles, and define permission rules +that govern user access to data and services in your application. For +more information, see Security & Token +Authentication.

+

Use the POST method to add a user to a group. If the named group does +not yet exist, an error message is returned.

+
+

Request syntax

+
curl -X POST https://api.usergrid.com/<org_id>/<app_id>/groups/<uuid | groupname>/users/<uuid | username>
+
+
+
+
+

Request URI

+
POST /<org_id>/<app_id>/groups/<uuid | groupname>/users/<uuid | username>
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + + + + +
ParameterDescription
arg uuid | string org_idOrganization UUID or organization name
arg uuid | string app_idApplication UUID or application name
arg uuid | string groupnameUUID or name of the group
arg uuid | string usernameUUID or username of user
+
+
+

Example

+

Note: Although not shown in the API examples below, you need to +provide a valid access token with each API call. See Authenticating +users and application +clients +for details.

+
+
+

Request

+
curl -X POST "https://api.usergrid.com/my-org/my-app/groups/mynewgroup/users/john.doe"
+
+
+
+
+

Response

+
{
+    "action": "post",
+    "application": "7fb8d891-477d-11e1-b2bd-22000a1c4e22",
+    "params": {},
+    "path": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users",
+    "uri": "https://api.usergrid.com/22000a1c4e22-7fb8d891-477d-11e1-b2bd/7fb8d891-477d-11e1-b2bd-22000a1c4e22/groups/a668717b-67cb-11e1-8223-12313d14bde7/users",
+    "entities": [{
+        "uuid": "6fbc8157-4786-11e1-b2bd-22000a1c4e22",
+        "type": "user",
+        "name": "John Doe",
+        "created": 1327517852364015,
+        "modified": 1327517852364015,
+        "activated": true,
+        "email": "john.doe@mail.com",
+        "metadata": {
+            "connecting": {
+                "owners":"/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/connecting/owners"
+            },
+            "path": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22",
+            "sets": {
+                "rolenames": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/rolenames",
+                "permissions": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/permissions"
+            },
+            "collections":{
+                "activities":"/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/activities",
+                "devices": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/devices",
+                "feed":"/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/feed",
+                "groups": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/groups",
+                "roles":"/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/roles",
+                "following": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/following",
+                "followers": "/groups/a668717b-67cb-11e1-8223-12313d14bde7/users/6fbc8157-4786-11e1-b2bd-22000a1c4e22/followers"
+            }
+        },
+        "picture": "https://www.gravatar.com/avatar/90f823ba15655b8cc8e3b4d63377576f",
+        "username": "john.doe"
+    }],
+    "timestamp": 1331066031380,
+    "duration": 64,
+    "organization" : "my-org",
+    "applicationName": "my-app"
+}
+
+
+
+
+
+

Removing a user from a group

+

Use the DELETE method to remove a user from the specified group.

+
+

Request syntax

+
curl -X DELETE https://api.usergrid.com/<org>/<app>/groups/<group>/users/<user>"
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + + + + +
ParameterDescription
orgOrganization UUID or organization name
appApplication UUID or application name
groupUUID or name of the group
userUUID, username or email of user to be deleted
+
+
+

Example request

+
curl -X DELETE https://api.usergrid.com/your-org/your-app/groups/someGroup/users/someUser
+
+
+
+
+

Example response

+
{
+  "action" : "delete",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : { },
+  "path" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users",
+  "uri" : "https://api.usergrid.com/your-org/your-app/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users",
+  "entities" : [ {
+    "uuid" : "74d2d7da-e694-11e3-b0c6-4d2664c8e0c3",
+    "type" : "user",
+    "name" : "someUser",
+    "created" : 1401301104077,
+    "modified" : 1401301104077,
+    "username" : "someUser",
+    "email" : "your-org@apigee.com",
+    "activated" : true,
+    "picture" : "http://www.gravatar.com/avatar/0455fc92de2636fc7a176cc5d298bb78",
+    "metadata" : {
+      "path" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3",
+      "sets" : {
+        "rolenames" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/roles",
+        "permissions" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/permissions"
+      },
+      "collections" : {
+        "activities" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/activities",
+        "devices" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/devices",
+        "feed" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/feed",
+        "groups" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/groups",
+        "roles" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/roles",
+        "following" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/following",
+        "followers" : "/groups/cd796d0a-b90c-11e3-83de-83ceb9965c26/users/74d2d7da-e694-11e3-b0c6-4d2664c8e0c3/followers"
+      }
+    }
+  } ],
+  "timestamp" : 1401751485776,
+  "duration" : 220,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/user-management/groups.html b/content/docs/user-management/groups.html new file mode 100644 index 0000000000..0dac8a2a4b --- /dev/null +++ b/content/docs/user-management/groups.html @@ -0,0 +1,412 @@ + + + + + + + + + + + Groups — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Groups

+

You can organize app users into groups. Groups have their own Activity +Feed, their own permissions and be a useful alternative to Roles, +depending on how you model your data. Groups were originaly designed to +emulate Facebook Groups, so they will tend to function about the same +way Facebook Groups would.

+

Groups are hierarchical. Every member of the group +/groups/california/san-francisco is also a member of the group +/groups/california.

+

Groups are also a great way to model things such a topic subscriptions. +For example, you could allow people to subscribe (i.e. become a member +of the group and be alerted via Activities) to /groups/memes/dogs/doge +or subscribe to all /groups/memes/dogs

+
+

General properties

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
uuidUUIDGroup’s unique entity ID
typestringType of entity, in this case “user”
createdlongUNIX timestamp of entity creation
modifiedlongUNIX timestamp of entity modification
pathstringValid slash-delimited group path (mandatory)
titlestringDisplay name
+
+
+

Set properties

+ +++++ + + + + + + + + + + + + + + + + + + + + +
SetTypeDescription
connectionsstringSet of connection types (e.g., likes)
rolenamesstringSet of roles assigned to a group
credentialsstringSet of group credentials
+
+
+

Collections

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
CollectionTypeDescription
usersuserCollection of users in the group
activitiesactivityCollection of activities a user has performed
feedactivityInbox of activity notifications a group has received
rolesroleSet of roles to which a group belongs
+
+
+ + +
+
+
+ + +
+ +
+

+ © Copyright 2013-2015, Apache Usergrid. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/user-management/messagee-example.html b/content/docs/user-management/messagee-example.html new file mode 100644 index 0000000000..09e7b42ed3 --- /dev/null +++ b/content/docs/user-management/messagee-example.html @@ -0,0 +1,497 @@ + + + + + + + + + + + App Example - Messagee — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

App Example - Messagee

+

Messagee is a simple Twitter-style messaging application that leverages +the extensive functionality of Usergrid. This section describes some of +the features of Messagee.

+

There are three client versions of Messagee:

+ +

The sections below describe how to create a new app, enter some test +users, and run the app. You also learn how to use the Usergrid admin +portal, a user interface that streamlines data and application +management in the Usergrid system. The portal is also a reference +application that shows how to incorporate Usergrid APIs with JavaScript.

+
+

Creating a user account in Usergrid

+

Go to the Usergrid portal and login. If you are new to Usergrid, sign up +for an account, specifying an organization (e.g., the name of your +company or project team) and a username and password that you can use to +authenticate. Because Usergrid are designed for use by development +teams, the same username can be associated with one or more +organizations.

+

If you create a new account, you receive a confirmation email that +contains a URL that you must click to activate the account. After this, +simply log in to the portal with your username and password.

+../_images/login.png +
+
+

Creating an app and users

+

When you have logged in, you need to create a new application.

+../_images/portal1.png +
+

STEP 1

+

Enter a unique application name. The name must be unique to avoid a +conflict with another user running the same application.

+../_images/portal2.png +
+
+

STEP 2

+

Make sure that the portal shows the application name you entered as the +active application beneath the Applications menu (1).

+

If the correct name is not displayed, click the menu and select your +application. Next, you need to populate a test user user-test-1 that is +going to log in to your copy of the server-side Messagee app.

+
+
+

STEP 3

+

Click the Users box on the left side of the console (2).

+../_images/portal3.png +
+
+

STEP 4

+

Click the Add button and enter the user information for your application +in the pop-up window (be sure to create a password you can remember), +and then click the Create button. Repeat these steps to create a second +username test-user-2.

+../_images/portal4.png +
+
+

STEP 5

+

When you have finished all these steps, you have a new application and +two new users.

+../_images/portal5.png +

Now that you have created a uniquely named copy of the Messagee +application as well as two user accounts (test-user-1 and test-user-2), +you are ready to test out the Messagee app. Use test-user-1 to log in to +the app, and test-user-2 as the user to follow.

+

To continue with the example, follow the instructions for a client app +(iOS client, Android client, or HTML5 client).

+
+
+
+

iOS client

+

Messagee is available as an iPhone app that uses Usergrid and RestKit. +The source for the iOS version of Messagee is available in the +/samples/messagee directory of the Usergrid iOS SDK

+

Here are the steps to run the Messagee app on iOS:

+
+

STEP 6

+

Run Steps 1-5 under Creating an app and users. These steps create a +unique instance of the Messagee app on the server and two test users, +test-user-1 and test-user-2.

+
+
+

STEP 7

+

Access the Messagee server app by typing a URL similar to the following +into your iOS mobile client (replace with the unique name of your +application): https://api.usergrid.com//index.html

+../_images/iOS1chooseapp.jpg +
+
+

STEP 8

+

On the mobile client, complete the registration information and click +Register.

+../_images/iOS2register.jpg +
+
+

STEP 9

+

Log in to the Messagee app by entering the test-user-1 account +information created previously, and click the Sign in button.

+user-management/iOS3signin.jpg +
+
+

STEP 10

+

At this point, the message board is empty:

+../_images/iOS5emptyfeed.jpg +
+
+

STEP 11

+

To post a message using the app, click the top-right icon in the message +board to create a message, write the message text, and send it by +clicking Post.

+../_images/iOS6newmsg.jpg +

Note: The posted message should appear in the message board within few +seconds.

+../_images/iOS7feed1msg.jpg +
+
+

STEP 12

+

For your instance of the Messagee application to act like Twitter, you +need to “follow” another user.

+

In the message board, click Add People and add test-user-2 as a person +that test-user-1 follows.

+user-management/iOS9followme.jpg +
+
+

STEP 6

+

Log in as test-user-2 and post a message as this user to the message +board.

+

Go back and log in as user test-user-1. Because test-user-1 follows +test-user-2, you should see the message sent by test-user-2 in the +message board.

+../_images/iOS10seeusermsg.jpg +
+
+
+

iOS SDK

+

If you want to write iOS applications that connect to Usergrid, +download the Usergrid iOS +SDK.

+

Note: The Messagee iOS application uses RestKit, a popular REST +framework for iOS, to communicate with Usergrid. Because Usergrid use a +REST API, you can use any REST framework to talk with the service. +However, the official Usergrid iOS SDK provides a more convenient +communication mechanism that you should use unless you’re already using +RestKit or some other framework in your project.

+
+
+

Android client and SDK

+

Messagee is available as a sample Android app that acts as a Usergrid +client. The source for the Android version is packaged with the Usergrid +Android SDK in the /samples/messagee directory.

+

Download the Usergrid Android +SDK

+
+
+

Javascript/HTML5 client and SDK

+

Messagee is also available as a sample HTML5 app that behaves in much +the same way as the two previous examples. The source for the HTML5 +version is packaged with the Usergrid Javascript/HTML5 SDK in the +/samples/messagee directory.

+

Download the Usergrid Javascript/HTML5 +SDK

+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/user-management/user-connections.html b/content/docs/user-management/user-connections.html new file mode 100644 index 0000000000..f1778f7ee9 --- /dev/null +++ b/content/docs/user-management/user-connections.html @@ -0,0 +1,372 @@ + + + + + + + + + + + Social Graph Connections — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Social Graph Connections

+

One of the most useful features of Usergrid is the ability to create +connections between entities, which allow you to model arbitrary +relationships between entities. This feature is particularly powerful +when applied to user entities by allowing you to model complex social +graphs between users as well as groups of users.

+
+

Following/followers

+

To make the social graph possibilities of entity connections even easier +to achieve, Usergrid also has special support for a default +following/followers relationship, which offers these additional +features:

+

Reciprocal connection: If a following connection is made between a user +and another user, a reciprocal followers relationship will be created +automatically. In contrast, all of other entity connections are one-way, +meaning any reciprocal relationship must be created manually.

+

Activity feed subscription: The followed user’s activities will +automatically be posted to the following user’s activity feed. For +example, if Arthur is following Ford, then any activities published by +Ford that Arthur is allowed to see will appear in Arthur’s activity +feed.

+
+
+

Creating a following/followers connection

+

To create a following/followers connection between two entities, create +the connection as you would any generic entity connection. For full +details on creating connections, see Connecting +entities.

+

For example, the following request would create a following/followers +relationship between two user entities with the usernames ‘Fred’ and +‘Barney’:

+
POST https://api.usergrid.com/your-org/your-app/users/barney/following/users/fred
+
+
+

Note

+

Please note that this only works when you POST a following +connection. Creating a follower connection would not create a reciprocal +following connection.

+

This would retrieve a list of the users that Barney is following:

+
GET https://api.usergrid.com/your-org/your-app/users/barney/following
+
+
+

And this would retrieve a list of users that are following Fred:

+
GET https://api.usergrid.com/your-org/your-app/users/fred/followers
+
+
+
+
+
+

Creating other connections

+

You can extend this connection structure to create connections using any +relationship. For example, you could use likes to denote a connection +between a user and his dog with this POST:

+
POST https://api.usergrid.com/your-org/your-app/users/Fred/likes/dogs/Dino
+
+
+

Note that in this case a reciprocal connection is not automatically +created. To do so you would need to manually create the reciprocal +connection with another POST such as:

+
POST https://api.usergrid.com/your-org/your-app/dogs/Dino/liked_by/users/Fred
+
+
+

For more information on using entity connections, see Connecting +entities.

+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/user-management/user-management.html b/content/docs/user-management/user-management.html new file mode 100644 index 0000000000..0fbfdb2e83 --- /dev/null +++ b/content/docs/user-management/user-management.html @@ -0,0 +1,386 @@ + + + + + + + + + + + User management & social graph — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

User management & social graph

+

Whether you’re developing apps for mobile or the Web, it’s almost +certain that you will need to be able to handle user management, as well +as offer the types of social features users have come to expect from a +rich app experience. Usergrid makes all of this easy with default entity +types and functionality available right out of the box. From user +registration and profiles to login and authentication to activity feeds +and social graph, you can create a social experience quickly and easily +with just a few types of API calls.

+
+

User management

+

The default user entity in Usergrid is designed to model app users, +meaning registering users and managing their profiles is as simple as +sending and updating JSON via the API. Used in conjunction with our +available social graph, as well as our OAuth 2.0 authentication and +token authorization features, you have all the tools you need to manage +your user base.

+

Learn more about:

+ +
+
+

Group management

+

One of the most basic social features of any app is the ability to +create groups of users to limit shared access to user or other app data. +The default group entity in Usergrid was designed for this exact +purpose. Associate a user with as many groups or sub-groups as you need, +then apply permissions or roles to define shared access to Usergrid +data.

+

Learn more about:

+ +
+
+

Social connections

+

To create a rich social graph, your app needs to be able to create +connections between users. Usergrid makes this process lightweight by +allowing you to create social connections and generic entity connections +between users to model relationships by working with simple URI paths.

+

For example, you could create a ‘likes’ relationship between two users +with a POST:

+
https://api.usergrid.com/your-org/your-app/users/Arthur/likes/users/Ford
+
+
+

You could then retrieve all the users Arthur ‘likes’ with a GET to +populate a list in your UI:

+
https://api.usergrid.com/your-org/your-app/users/Arthur/likes
+
+
+

Learn more about:

+ +
+
+

Activity feeds

+

Activity feeds can be an essential way of establishing a social +dimension of your user experience. Allow users to actively publish +activities, such as status messages, or have your application code +passively publish activities based on user actions, such as posting a +photo. Activity feeds can be created and shared at both the user and +group level, giving you the flexibility to present activity feeds that +are most relevant to your users.

+

Learn more about:

+ +
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/user-management/working-user-data.html b/content/docs/user-management/working-user-data.html new file mode 100644 index 0000000000..868af24a2e --- /dev/null +++ b/content/docs/user-management/working-user-data.html @@ -0,0 +1,719 @@ + + + + + + + + + + + Working with User Data — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Working with User Data

+

You can store and manage user data as User entities. With user data in +your application, you can add support for a wide variety of features +common to mobile apps. For example, you can:

+
    +
  • Control access to data by defining permission rules. (See Security & +token authentication for +more.)
  • +
  • Present content specific to each user, such as their list of +favorites.
  • +
  • Support social features, such as letting users “follow” one another, +for example.
  • +
+

In mobile applications, data about users is typically added by users +themselves when they register through your app. The topics in this +section provide specific cURL and SDK-specific examples for getting +things done with user data.

+
+

Creating users

+

A user entity represents an application user. Using API Services you can +create, retrieve, update, delete, and query user entities. See User +entity properties for a list of +the system-defined properties for user entities. In addition, you can +create user properties specific to your application.

+
+

Request Syntax

+
curl -X POST "https://api.usergrid.com/your-org/your-app/users" -d '{ "username": "john.doe", "email": "john.doe@gmail.com", "name": "John Doe", "password": "test1234" }'
+
+
+

Use the POST method to create a new user in the users collection.

+
+
+

Request URI

+
POST /<org_id>/<app_id>/users
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription
uuid | org_idOrganization UUID or organization name.
uuid | app_idApplication UUID or application name.
request bodyOne or more sets of user properties.
+

The username is mandatory and must be unique. Here’s an example:

+
{
+    "username" : "john.doe",
+    "email" : "john.doe@gmail.com",
+    "name" : "John Doe",
+    "password" : "test1234"
+}
+
+
+

Although the password parameter is not mandatory, if you don’t specify +it, the user will not be able to log in using username and password +credentials. If a password is not specified for the user, and you’re an +Admin, you can set a password for the user (see Changing a User +Password).

+

__ Note__: The username can contain any combination of characters, +including those that represent letters, numbers, and symbols.

+
+
+

Example

+

Note: Although not shown in the API examples below, you need to +provide a valid access token with each API call. See Authenticating +users and application +clients +for details.

+
+
+

Request

+
curl -X POST "https://api.usergrid.com/my-org/my-app/users" -d '{"username":"john.doe","email":"john.doe@gmail.com","name":"John Doe"}'
+
+
+
+
+

Response

+
{
+  "action" : "post",
+  "application" : "db1e60a0-417f-11e3-9586-0f1ff3650d20",
+  "params" : { },
+  "path" : "/users",
+  "uri" : "https://api.usergrid.com/steventraut/mynewapp/users",
+  "entities" : [ {
+    "uuid" : "8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc",
+    "type" : "user",
+    "name" : "John Doe",
+    "created" : 1390533228622,
+    "modified" : 1390533228622,
+    "username" : "john.doe",
+    "email" : "john.doe@gmail.com",
+    "activated" : true,
+    "picture" : "http://www.gravatar.com/avatar/e13743a7f1db7f4246badd6fd6ff54ff",
+    "metadata" : {
+      "path" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc",
+      "sets" : {
+        "rolenames" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/roles",
+        "permissions" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/permissions"
+      },
+      "collections" : {
+        "activities" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/activities",
+        "devices" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/devices",
+        "feed" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/feed",
+        "groups" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/groups",
+        "roles" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/roles",
+        "following" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/following",
+        "followers" : "/users/8ae8a6ea-84a5-11e3-884d-f18e8f6fb3bc/followers"
+      }
+    }
+  }],
+  "timestamp" : 1390533228619,
+  "duration" : 142,
+  "organization" : "my-org",
+  "applicationName" : "my-app"
+}
+
+
+
+
+
+

Retrieving user data

+

You can retrieve data about users through cURL or one of the SDKs. Each +provides a way to filter the list of users by data associated with the +user, such as username or UUID, or other properties in the user entity.

+

See User entity properties for +a list of the system-defined properties for user entities. In addition, +you can create user properties specific to your application.

+
+

Request Syntax

+
curl -X GET "https://api.usergrid.com/your-org/your-app/users"
+
+
+

Use the GET method to retrieve user data.

+
+
+

Request URI

+
GET /<org_id>/<app_id>/users/<uuid | username | email_address | ?ql=query_string>
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + +
ParameterDescription
uuid | org_idOrganization UUID or organization name
uuid | app_idApplication UUID or application name
user identifierUser UUID, username, or email address.
+

The alias /users/me can be used in place of the current user’s uuid, +username, or email address. Note: The /users/me endpoint is +accessible only if you provide an access token with the request (see +Authenticating users and application +clients). +If you make an anonymous (“guest”) call, the system will not be able to +determine which user to return as /users/me.

+

Note: The username can contain any combination of characters, +including those that represent letters, numbers, and symbols.

+
+
+

Example

+

Note: Although not shown in the API examples below, you need to +provide a valid access token with each API call. See Authenticating +users and application +clients +for details.

+

Requests

+
# Get a user by username.
+curl -X GET "https://api.usergrid.com/my-org/my-app/users/jane.doe"
+
+# Get a user by UUID.
+curl -X GET "https://api.usergrid.com/my-org/my-app/users/a407b1e7-58e8-11e1-ac46-22000a1c5a67e"
+
+# Get a user by email.
+curl -X GET "https://api.usergrid.com/my-org/my-app/users/jane.doe@gmail.com"
+
+# Get user data filtering by their city property value.
+curl -X GET "https://api.usergrid.com/my-org/my-app/users?ql=select%20*%20where%20adr.city%3D'Chicago'"
+
+
+

Response

+
{
+    "action" : "get",
+    "application" : "1c8f60e4-da67-11e0-b93d-12313f0204bb8",
+    "params" : {
+        "_": [
+            "1315524419746"
+        ]
+    },
+    "path" : "https://api.usergrid.com/12313f0204bb-1c8f60e4-da67-11e0-b93d/1c8f60e4-da67-11e0-b93d-12313f0204bb/users",
+    "uri" : "https://api.usergrid.com/005056c00008-4353136f-e978-11e0-8264/4353136f-e978-11e0-8264-005056c00008/users",
+    "entities" : [ {
+        "uuid" : "78c54a82-da71-11e0-b93d-12313f0204b",
+        "type" : "user",
+        "created" : 1315524171347008,
+        "modified" : 1315524171347008,
+        "activated" : true,
+        "email" : "jane.doe@gmail.com",
+        "metadata" : {
+            "path" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb",
+            "sets" : {
+                "rolenames" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/rolenames",
+                "permissions" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/permissions"
+            },
+            "collections" : {
+                "activities" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/activities",
+                "devices" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/devices",
+                "feed" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/feed",
+                "groups" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/groups",
+                "roles" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/roles",
+                "following" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/following",
+                "followers" : "/users/78c54a82-da71-11e0-b93d-12313f0204bb/followers"
+            }
+        },
+        "username" : "jane.doe"
+    }
+    ... Additional entities here if data for multiple users was returned...
+    ],
+    "timestamp" : 1315524421071,
+    "duration" : 107,
+    "organization" : "my-org",
+    "applicationName": "my-app"
+}
+
+
+
+
+
+

Updating & deleting user data

+

To update or delete a user, perform an update or delete on the +associated user entity as you would any other entity. For more +information and code samples, see Updating Data +Entities and +Deleting Data +Entities.

+
+
+

Changing a user password

+

Changing a user’s password

+
+

Request syntax

+
curl -X PUT https://api.usergrid.com/<org>/<app>/users/<username_or_email>/password -d '{oldpassword:<old_password>,newpassword:<new_password>}'
+
+
+

Parameters

+ ++++ + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription
orgOrganization UUID or organization name
appApplication UUID or application name
username_or_emailUsername or email of the user entity whose password you want to reset.
old_passwordUser entity’s old password.
new_passwordUser entity’s new password.
+

Note: If your request is authenticated with an application-level +token, then old_password is not required. For more, see Application +client +authentication.

+

Example request

+
curl -X PUT https://api.usergrid.com/my-org/my-app/users/john.doe/password -d '{"newpassword":"foo9876a","oldpassword":"bar1234b"}'
+
+
+

Example response

+
{
+  "action": "set user password",
+  "timestamp": 1355185897894,
+  "duration": 47
+}
+
+
+
+
+
+

Resetting a user password

+

Resetting a user’s password

+

Usergrid provides a standard password reset flow that can be implemented +to allow a user to reset their password without having to provide their +old password. The most common use of this would be a ‘Forgot password?’ +feature in your app.

+

Note that you can also implement your own password reset flow using +application-level authentication and the /password endpoint. For more, +see Changing a user password.

+

To use the Usergrid password reset flow, do the following:

+
+

STEP 1: Get the password reset request form.

+

Make a GET request to the following:

+
/users/<username>/resetpw
+
+
+

For example, using cURL, a request to reset the password for a user with +username ‘someUser’ would look like this:

+
curl -x GET https://api.usergrid.com/your-org/your-app/users/someUser/resetpw
+
+
+
+
+

STEP 2: Display the returned password reset request form to the user.

+

The request to /resetpw will return the HTML for the standard +Usergrid password reset request form that you will display to your user. +The request form requires the users to provide their username as well as +answer a standard CAPTCHA challenge:

+
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Reset Password</title>
+<link rel="stylesheet" type="text/css" href="/css/styles.css" />
+</head>
+<body>
+    <div class="dialog-area">
+
+        <form class="dialog-form" action="" method="post">
+            <fieldset>
+                <p>
+                    Enter the captcha to have your password reset instructions sent to
+                    someUser@adomain.com
+                </p>
+                <p id="human-proof"></p>
+                <script type="text/javascript" src="https://www.google.com/recaptcha/api/challenge?k=6LdSTNESAAAAAKHdVglHmMu86_EoYxsJjqQD1IpZ"></script>
+
+                <p class="buttons">
+                    <input type="submit" value="submit" />
+                </p>
+            </fieldset>
+        </form>
+    </div>
+</body>
+</html>
+
+
+

You can apply any additional styling you wish to the form to make it +match the style of your app before displaying it to the user.

+
+
+

STEP 3: Let Usergrid handle the rest!

+

Once the user submits the form with their username, they will receive an +email from Usergrid that contains a link to the password reset form, +where they can specify a new password. The user entity will be updated +immediately.

+
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/using-usergrid/creating-a-new-application.html b/content/docs/using-usergrid/creating-a-new-application.html new file mode 100644 index 0000000000..f8d3abb77f --- /dev/null +++ b/content/docs/using-usergrid/creating-a-new-application.html @@ -0,0 +1,336 @@ + + + + + + + + + + + Creating a new application — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Creating a new application

+
+

Creating an application

+

You can use the admin portal to create applications. An application +represents the data associated with your app. Through an application, +you handle the entities associated with your app, including users, +devices, events, and so on.

+

To create a new application with the admin portal:

+
    +
  1. In the admin portal, from the dropdown menu at the far top left, +select the organization to which you will add the new application.
  2. +
  3. Click the ADD NEW APP button, located at the top of the screen, next +to the application drop-down.
  4. +
  5. In the dialog box, enter a new application name, then click the +Create button. Your new application will automatically be selected in +the applications drop-down menu.
  6. +
+

Applications can also be created programatically with a POST request +to the API. For more, see +Application.

+
+
+

Securing an application

+

If this is going to be a production application, be sure to configure +security roles that provide only the level of access your users will +need. For more on security, see Security Best +Practices .

+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/using-usergrid/creating-account.html b/content/docs/using-usergrid/creating-account.html new file mode 100644 index 0000000000..757a156b06 --- /dev/null +++ b/content/docs/using-usergrid/creating-account.html @@ -0,0 +1,347 @@ + + + + + + + + + + + Creating a Usergrid Account — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Creating a Usergrid Account

+

To get started using the Usergrid, you’ll need an Usergrid account. +(Before reading this, you should already be familiar with what Usergrid +can do to support your apps. If you’re still curious about that, you +might want to read Usergrid features first.)

+

With an account, you get the following useful things:

+
    +
  • A sandbox application you can try things with (we automatically +create one for you with your new account). The sandbox is a +partitioned area of the data store where you can add example data and +try out API calls. The sandbox isn’t secure, but it’s handy to play +in. For more about the sandbox, see Using Your Application +Sandbox.
  • +
  • The ability to create more applications (in addition to the sandbox). +You can (and should!) make these as secure as you need to. These are +the applications that you’ll have behind the apps you make available +to your users.
  • +
  • Access to the Admin Portal. In the portal, you can do the following:
      +
    • Create and manage applications.
    • +
    • Manage your app’s users, including access levels.
    • +
    • Manage the data in your app.
    • +
    • Manage app features, including push notifications, activities, +analytics, and so on.
    • +
    • Try out API calls with a shell command window.
    • +
    • To create an Usergrid account and see a very short tutorial to get +started with, go to the get started page of the Portal.
    • +
    +
  • +
+
+

Next steps

+

Ready to learn and do more?

+
    +
  • Install an SDK that will be most useful for your application +environment. For more about Usergrid’s SDKs, see +SDKs.
  • +
  • Review Usergrid features for information on concepts and features.
  • +
  • Consult the API Reference for usage details.
  • +
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/using-usergrid/using-a-sandbox-app.html b/content/docs/using-usergrid/using-a-sandbox-app.html new file mode 100644 index 0000000000..b39fb491ae --- /dev/null +++ b/content/docs/using-usergrid/using-a-sandbox-app.html @@ -0,0 +1,372 @@ + + + + + + + + + + + Using a Sandbox Application — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Using a Sandbox Application

+
+

What is the sandbox application?

+

When you create a new Usergrid account (see Creating an Usergrid +Account) to use services for developers, +Usergrid creates a new application for you on its servers. With the new +application, called “sandbox,” you can add your own example data and try +out API calls that do things with the data. Be sure to see Using the API +for suggestions.

+
+
+

Is the sandbox secure?

+

To keep things simple and make it easier for you to try things out, the +sandbox application has all authentication disabled. That way, it +doesn’t require an access token for application-level calls to the API. +Permissions are so open on the sandbox application because its “guest” +role offers full permissions for all access paths – that is, GET, POST, +PUT, and DELETE for /**. Learn more about roles and permissions in +Managing access by defining permission rules.

+ +

Warning

+

+

Never use a sandbox app for production. Keep in mind that the lack of +authentication means that a sandbox application is not secure enough for +important or sensitive data. A sandbox is just for experimentation while +you learn how the services work, and should never be used for a +production application. As with other Usergrid applications you create, +a sandbox application is an area of the data store where you can put +your own data. You can create as many other applications as you like, +including more sandbox applications. When it comes to production +(secured) applications, a good rule of thumb is to create one +application for each mobile app you develop.

+

+
+
+

Creating a New Sandbox Application

+

You may want to create (or re-create) a sandbox application. For +example, you may want to create a sandbox application for another +organization or you may want to create another application for testing +purposes.

+ +

Warning

+

Guest Role should never be given full permissions. Giving the guest role +full permissions should be used only for testing and should not be used +in production. Before you make your app “live”, you should remove the +guest permissions for /**.

+

Use the following steps to create a sandbox app:

+
    +
  1. Create a new application using the admin portal. You can name the +application whatever you like (including “sandbox”).
  2. +
  3. Set full access permissions for the guest role, as follows:
      +
    1. In the admin portal, click Users, then click Roles.
    2. +
    3. On the Roles page, in the list of roles, click Guest.
    4. +
    5. For the Guest role, under Permissions, click Add Permission.
    6. +
    7. In the New Permission dialog, enter the following in the Path box: +/**
    8. +
    9. Select the following check boxes: get, post, put, and delete.
    10. +
    11. Click the Add button.
    12. +
    13. If there are other permissions listed, delete them.
    14. +
    +
  4. +
+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/docs/using-usergrid/using-the-api.html b/content/docs/using-usergrid/using-the-api.html new file mode 100644 index 0000000000..283a7e73f7 --- /dev/null +++ b/content/docs/using-usergrid/using-the-api.html @@ -0,0 +1,506 @@ + + + + + + + + + + + Using the API — Apache Usergrid 1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+
+
+ +
+
+
+
+ +
+

Using the API

+

Usergrid uses a pure REST (Representational State Transfer) API built as +a collection of resources. Resource locations are described by paths +that are related intrinsically to collections and entities in +collections.

+

This section gives several examples of how to construct API requests. To +focus on what’s important, the examples use an abbreviated path that +starts after the application UUID, or application name. For example, +instead of giving a fully qualified path name as in:

+
https://api.usergrid.com/your-org/your-app/users
+
+
+

the example simply lists this:

+
/users
+
+
+
+

Supported HTTP methods

+

When building a REST API, the challenge is to represent the data and the +action upon the data as a path to a resource that can be created, +retrieved, updated, or deleted. The HTTP methods POST, GET, PUT, and +DELETE correspond to the actions that are applied to resources.

+
+
+

Base URL

+

The base url for all requests made to Usergrid depends on where you have +Usergrid installed. If you are using Apigee’s trial Usergrid service, +the base URL is https://api.usergrid.com.

+
+
+

Request construction

+

Usergrid interprets the URL resource path as a list of names, UUIDs, or +queries. The basic path format is:

+
https://api.usergrid.com/<org-uuid|org-name>/<app-uuid|app-name>/<collection-name>/<entity-uuid|entity-name>
+
+
+

Note: You cannot mix UUIDs and names in the URL resource path. For +example, the following is incorrect:

+
https://api.usergrid.com/your-org/62de5d97-d28c-11e1-8d5c-12313b01d5c1/users/john.doe
+
+
+
+
+

Accessing collections

+

To access all entities in a collection, specify the path as follows:

+
/users
+
+
+

Such a request retrieves the first 10 entities in the collection /users +sorted by their entity UUID.

+
+
+

Accessing entities

+

To access an entity in a collection, specify the path as follows:

+
/<collection>/<uuid|name>
+
+
+

where <collection> is the collection name, and is the entity’s uuid +or name.

+

To access a user in the users collection, specify the path as follows:

+
/users/<uuid|username|email_address>
+
+
+

where <uuid|username|email_address> is the user’s uuid, username, or +email address.

+

For example, the following request retrieves the entity named dino from +the dogs collection:

+
/dogs/dino
+
+
+
+
+

Issuing queries

+

You can issue a query in an API request that retrieves items from a +collection. Here is the typical format for queries:

+
/<collection>?ql=<query>
+
+
+

where is a query in the query language.

+

For example, this request retrieves users whose Facebook first name is +john:

+
/users?ql=select * where facebook.first_name ='john'
+
+
+

For further information about queries, see Querying your +Data

+
+
+

Authentication (OAuth)

+

Usergrid implements the OAuth 2.0 standard for authenticating users, +clients and API requests.

+

Generally, you will generate a token for every user of your app by +providing the user’s username and password. The token can then be sent +with all API requests to ensure each user is only able to access and +modify the resources you have granted them rights to.

+

Note that by default access tokens are not needed to make requests to +the default sandbox application in an organization.

+

For more information on generating and using access tokens, see +Authenticating users and application clients and Authenticating API +requests.

+
+
+

Response format

+

All API methods return a response object that typically contains an +array of entities:

+
{
+  "entities" : [
+    ...
+  ]
+}
+
+
+

Not everything can be included inside the entity, and some of the data +that gets associated with specific entities isn’t part of their +persistent representation. This is metadata, and it can be part of the +response as well as associated with a specific entity. Metadata is just +an arbitrary key/value JSON structure.

+

For example:

+
{
+  "entities" : {
+    {
+      "name" : "ed",
+      "metadata" : {
+        "collections" : ["activities", "groups", "followers"]
+      }
+    }
+  },
+  "metadata" : {
+    "foo" : ["bar", "baz"]
+  }
+}
+
+
+

For example, here is the response to a basic GET for a user entity:

+
{
+  "action" : "get",
+  "application" : "f34f4222-a166-11e2-a7f7-02e81adcf3d0",
+  "params" : { },
+  "path" : "/users",
+  "uri" : "https://api.usergrid.com/your-org/your-app/users",
+  "entities" : [ {
+    "uuid" : "503f17da-ec39-11e3-a0dd-a554b7fbd57a",
+    "type" : "user",
+    "created" : 1401921665485,
+    "modified" : 1401921665485,
+    "username" : "someUser",
+    "email" : "someUser@yourdomain.com",
+    "activated" : true,
+    "picture" : "http://www.gravatar.com/avatar/dc5d478e9c029853fbd025bed0dc51f8",
+    "metadata" : {
+      "path" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a",
+      "sets" : {
+        "rolenames" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/roles",
+        "permissions" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/permissions"
+      },
+      "collections" : {
+        "activities" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/activities",
+        "devices" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/devices",
+        "feed" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/feed",
+        "groups" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/groups",
+        "roles" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/roles",
+        "following" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/following",
+        "followers" : "/users/503f17da-ec39-11e3-a0dd-a554b7fbd57a/followers"
+      }
+    }
+  } ],
+  "timestamp" : 1401921673597,
+  "duration" : 12,
+  "organization" : "your-org",
+  "applicationName" : "your-app"
+}
+
+
+
+
+

SDKs

+

To make the integration of Usergrid features into your application code +quicker and easier, Usegrid offers SDKs in a variety of languages. The +SDKs contain language-specific methods that allow you to issue API +requests from your application code in your preferred language. SDKs are +available for the following languages:

+
    +
  • iOS
  • +
  • Android
  • +
  • JavaScript/HTML5
  • +
  • Node.js
  • +
  • Ruby
  • +
  • .NET
  • +
+

For more information, see SDKs.

+
+
+ + +
+
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/favicon.ico b/content/favicon.ico new file mode 100644 index 0000000000..11720d6ee2 Binary files /dev/null and b/content/favicon.ico differ diff --git a/content/font/FontAwesome.otf b/content/font/FontAwesome.otf new file mode 100755 index 0000000000..70125459f7 Binary files /dev/null and b/content/font/FontAwesome.otf differ diff --git a/content/font/fontawesome-webfont-eot.eot b/content/font/fontawesome-webfont-eot.eot new file mode 100755 index 0000000000..0662cb96bf Binary files /dev/null and b/content/font/fontawesome-webfont-eot.eot differ diff --git a/content/font/fontawesome-webfont-svg.svg b/content/font/fontawesome-webfont-svg.svg new file mode 100755 index 0000000000..2edb4ec34c --- /dev/null +++ b/content/font/fontawesome-webfont-svg.svg @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/font/fontawesome-webfont-ttf.ttf b/content/font/fontawesome-webfont-ttf.ttf new file mode 100755 index 0000000000..d365924691 Binary files /dev/null and b/content/font/fontawesome-webfont-ttf.ttf differ diff --git a/content/font/fontawesome-webfont-woff.woff b/content/font/fontawesome-webfont-woff.woff new file mode 100755 index 0000000000..b9bd17e158 Binary files /dev/null and b/content/font/fontawesome-webfont-woff.woff differ diff --git a/content/img/alberto.jpg b/content/img/alberto.jpg new file mode 100644 index 0000000000..0668d6a36e Binary files /dev/null and b/content/img/alberto.jpg differ diff --git a/content/img/alex.png b/content/img/alex.png new file mode 100644 index 0000000000..aec34f61dd Binary files /dev/null and b/content/img/alex.png differ diff --git a/content/img/apache_usergrid_favicon.png b/content/img/apache_usergrid_favicon.png new file mode 100644 index 0000000000..956656509f Binary files /dev/null and b/content/img/apache_usergrid_favicon.png differ diff --git a/content/img/apache_usergrid_logo_white.png b/content/img/apache_usergrid_logo_white.png new file mode 100644 index 0000000000..7f316b5933 Binary files /dev/null and b/content/img/apache_usergrid_logo_white.png differ diff --git a/content/img/apache_usergrid_logo_white_small.png b/content/img/apache_usergrid_logo_white_small.png new file mode 100644 index 0000000000..953be54db3 Binary files /dev/null and b/content/img/apache_usergrid_logo_white_small.png differ diff --git a/content/img/check_flat/default.png b/content/img/check_flat/default.png new file mode 100755 index 0000000000..5a89765159 Binary files /dev/null and b/content/img/check_flat/default.png differ diff --git a/content/img/dave.jpg b/content/img/dave.jpg new file mode 100644 index 0000000000..e3a7691b82 Binary files /dev/null and b/content/img/dave.jpg differ diff --git a/content/img/ed.jpg b/content/img/ed.jpg new file mode 100644 index 0000000000..ed669c15ab Binary files /dev/null and b/content/img/ed.jpg differ diff --git a/content/img/egg-logo.png b/content/img/egg-logo.png new file mode 100644 index 0000000000..2169a2a36c Binary files /dev/null and b/content/img/egg-logo.png differ diff --git a/content/img/github.png b/content/img/github.png new file mode 100644 index 0000000000..f19ee0df7d Binary files /dev/null and b/content/img/github.png differ diff --git a/content/img/grey.png b/content/img/grey.png new file mode 100644 index 0000000000..480557e3aa Binary files /dev/null and b/content/img/grey.png differ diff --git a/content/img/intellij.png b/content/img/intellij.png new file mode 100644 index 0000000000..2e8c480923 Binary files /dev/null and b/content/img/intellij.png differ diff --git a/content/img/jeff.jpg b/content/img/jeff.jpg new file mode 100644 index 0000000000..0f4eff9f85 Binary files /dev/null and b/content/img/jeff.jpg differ diff --git a/content/img/michael_r.jpg b/content/img/michael_r.jpg new file mode 100644 index 0000000000..096d0f593e Binary files /dev/null and b/content/img/michael_r.jpg differ diff --git a/content/img/mike_d.JPG b/content/img/mike_d.JPG new file mode 100644 index 0000000000..8dca2eee4b Binary files /dev/null and b/content/img/mike_d.JPG differ diff --git a/content/img/miked.jpg b/content/img/miked.jpg new file mode 100644 index 0000000000..8dca2eee4b Binary files /dev/null and b/content/img/miked.jpg differ diff --git a/content/img/nate.jpg b/content/img/nate.jpg new file mode 100644 index 0000000000..ccda068f1d Binary files /dev/null and b/content/img/nate.jpg differ diff --git a/content/img/rod.jpg b/content/img/rod.jpg new file mode 100644 index 0000000000..7533e1d6ca Binary files /dev/null and b/content/img/rod.jpg differ diff --git a/content/img/scott.jpg b/content/img/scott.jpg new file mode 100644 index 0000000000..91d2e4d9e5 Binary files /dev/null and b/content/img/scott.jpg differ diff --git a/content/img/shawn.jpg b/content/img/shawn.jpg new file mode 100644 index 0000000000..6baaa77985 Binary files /dev/null and b/content/img/shawn.jpg differ diff --git a/content/img/stliu.jpg b/content/img/stliu.jpg new file mode 100644 index 0000000000..9b1800fbce Binary files /dev/null and b/content/img/stliu.jpg differ diff --git a/content/img/strong.jpg b/content/img/strong.jpg new file mode 100644 index 0000000000..771bbf9d5a Binary files /dev/null and b/content/img/strong.jpg differ diff --git a/content/img/structure101.png b/content/img/structure101.png new file mode 100644 index 0000000000..1510620e75 Binary files /dev/null and b/content/img/structure101.png differ diff --git a/content/img/sungju.jpg b/content/img/sungju.jpg new file mode 100644 index 0000000000..939ac64745 Binary files /dev/null and b/content/img/sungju.jpg differ diff --git a/content/img/tim.jpg b/content/img/tim.jpg new file mode 100644 index 0000000000..9275e88733 Binary files /dev/null and b/content/img/tim.jpg differ diff --git a/content/img/todd.jpg b/content/img/todd.jpg new file mode 100644 index 0000000000..2f7637ea9a Binary files /dev/null and b/content/img/todd.jpg differ diff --git a/content/img/usergrid-logo.pdf b/content/img/usergrid-logo.pdf new file mode 100755 index 0000000000..b393160b41 Binary files /dev/null and b/content/img/usergrid-logo.pdf differ diff --git a/content/img/usergrid.png b/content/img/usergrid.png new file mode 100644 index 0000000000..d7b50ae4d4 Binary files /dev/null and b/content/img/usergrid.png differ diff --git a/content/img/usergrid_160.png b/content/img/usergrid_160.png new file mode 100644 index 0000000000..28ef4c53fb Binary files /dev/null and b/content/img/usergrid_160.png differ diff --git a/content/img/usergrid_200.png b/content/img/usergrid_200.png new file mode 100644 index 0000000000..c977d7c63d Binary files /dev/null and b/content/img/usergrid_200.png differ diff --git a/content/img/usergrid_300.png b/content/img/usergrid_300.png new file mode 100644 index 0000000000..3ebda90514 Binary files /dev/null and b/content/img/usergrid_300.png differ diff --git a/content/img/usergrid_300_transparent.png b/content/img/usergrid_300_transparent.png new file mode 100644 index 0000000000..f5ab64287f Binary files /dev/null and b/content/img/usergrid_300_transparent.png differ diff --git a/content/img/usergrid_400.png b/content/img/usergrid_400.png new file mode 100644 index 0000000000..01435eaabd Binary files /dev/null and b/content/img/usergrid_400.png differ diff --git a/content/img/usergrid_800.png b/content/img/usergrid_800.png new file mode 100644 index 0000000000..a30fc186c6 Binary files /dev/null and b/content/img/usergrid_800.png differ diff --git a/content/img/usergrid_card.png b/content/img/usergrid_card.png new file mode 100644 index 0000000000..f111f2ed9c Binary files /dev/null and b/content/img/usergrid_card.png differ diff --git a/content/img/usergrid_logo.png b/content/img/usergrid_logo.png new file mode 100644 index 0000000000..0532915a8d Binary files /dev/null and b/content/img/usergrid_logo.png differ diff --git a/content/img/usergrid_logo_205_50.png b/content/img/usergrid_logo_205_50.png new file mode 100644 index 0000000000..4af8807fe5 Binary files /dev/null and b/content/img/usergrid_logo_205_50.png differ diff --git a/content/img/usergrid_logo_260_50.png b/content/img/usergrid_logo_260_50.png new file mode 100644 index 0000000000..96b49983c6 Binary files /dev/null and b/content/img/usergrid_logo_260_50.png differ diff --git a/content/img/usergrid_logo_720.png b/content/img/usergrid_logo_720.png new file mode 100644 index 0000000000..c8cbf7d140 Binary files /dev/null and b/content/img/usergrid_logo_720.png differ diff --git a/content/img/usergrid_logo_720p.png b/content/img/usergrid_logo_720p.png new file mode 100644 index 0000000000..6e88a4d214 Binary files /dev/null and b/content/img/usergrid_logo_720p.png differ diff --git a/content/img/usergrid_logo_900_200.png b/content/img/usergrid_logo_900_200.png new file mode 100644 index 0000000000..42741165e8 Binary files /dev/null and b/content/img/usergrid_logo_900_200.png differ diff --git a/content/img/usergrid_logo_white.png b/content/img/usergrid_logo_white.png new file mode 100644 index 0000000000..f73299b11d Binary files /dev/null and b/content/img/usergrid_logo_white.png differ diff --git a/content/img/usergrid_profile_128.png b/content/img/usergrid_profile_128.png new file mode 100644 index 0000000000..71b792a64b Binary files /dev/null and b/content/img/usergrid_profile_128.png differ diff --git a/content/img/usergrid_profile_256.png b/content/img/usergrid_profile_256.png new file mode 100644 index 0000000000..b27f90316d Binary files /dev/null and b/content/img/usergrid_profile_256.png differ diff --git a/content/img/usergrid_profile_256_white.png b/content/img/usergrid_profile_256_white.png new file mode 100644 index 0000000000..fc3fc4b87a Binary files /dev/null and b/content/img/usergrid_profile_256_white.png differ diff --git a/content/img/usergrid_profile_512_margins.png b/content/img/usergrid_profile_512_margins.png new file mode 100644 index 0000000000..42a993480d Binary files /dev/null and b/content/img/usergrid_profile_512_margins.png differ diff --git a/content/img/usergrid_profile_64_white.png b/content/img/usergrid_profile_64_white.png new file mode 100644 index 0000000000..5a89767977 Binary files /dev/null and b/content/img/usergrid_profile_64_white.png differ diff --git a/content/img/usergrid_profile_background.png b/content/img/usergrid_profile_background.png new file mode 100644 index 0000000000..741d156a16 Binary files /dev/null and b/content/img/usergrid_profile_background.png differ diff --git a/content/img/usergrid_screencast_bg.png b/content/img/usergrid_screencast_bg.png new file mode 100644 index 0000000000..6179bca38d Binary files /dev/null and b/content/img/usergrid_screencast_bg.png differ diff --git a/content/img/usergrid_small_100.png b/content/img/usergrid_small_100.png new file mode 100644 index 0000000000..c06e7e5e94 Binary files /dev/null and b/content/img/usergrid_small_100.png differ diff --git a/content/img/usergrid_wiki.png b/content/img/usergrid_wiki.png new file mode 100644 index 0000000000..f443959183 Binary files /dev/null and b/content/img/usergrid_wiki.png differ diff --git a/content/img/yourkit.jpeg b/content/img/yourkit.jpeg new file mode 100644 index 0000000000..4a53b77e79 Binary files /dev/null and b/content/img/yourkit.jpeg differ diff --git a/content/index.html b/content/index.html new file mode 100644 index 0000000000..9416909fcc --- /dev/null +++ b/content/index.html @@ -0,0 +1,262 @@ + + + + + + Apache Usergrid — the BaaS not made for Hipsters + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+

The BaaS Framework you run

+

Build Apps not Servers! Whether you need to support one App or a hundred, Usergrid is your backend. As easy as a LAMP stack, but built for mobile. + Get Apps to production in record time and stop wasting cycles writing server-side code.

+ Complete SDKs for iOS, Android, HTML5/JS, Node.js, Ruby, Java, .NET, and PHP. Open source since 2011.

+
+ +
+ + + +
+ +
+
+
+ +
+
+
+
+
+

Users

+

Sign up users, log in, reset passwords and more, in just one API call. You can put users in groups, assign roles or permissions, let users follow each other and access everything via OAuth 2.0, without writing a single line of server code.

+
+
+
+

Data

+

If you can express it in JSON, we can store it! Underneath everything is stored in a standard Cassandra instance, but we’ve added the ability to retrieve data via an SQL-like syntax, manage collections and connections between entities.

+
+
+
+

Files

+

Our asset storage can handle anything from text files to videos of several terrabytes, with automatic content-detection and full URL access control. In the back, everything goes Amazon S3 or other preferred cloud file store.

+
+
+
+
+
+

SDKs

+

We have full SDKs for iOS, Android, and HTML5/JS but also node.js, Ruby on Rails, pure pure Ruby, server-side Java, .NET / Windows and PHP!

+
+
+
+

Java-based

+

We build on standard Java components, such as Jersey, Jackson, Apache Cassandra and Lucene. That means you get operational predictability, all the benefits of the JVM, and easy extensibility.

+
+
+
+

Trusted

+

Usergrid is deployed by Korea Telecom, Globo, Apigee and many Fortune 500 companies. Our biggest deployments have hundreds of nodes and handle millions of users.

+
+
+
+ + +
+ +
+ +
+
+ +
+
+

About the Project

+

Usergrid is an open-source Backend-as-a-Service (“BaaS” or “mBaaS”) composed of an integrated distributed NoSQL database, application layer and client tier with SDKs for developers looking to rapidly build web and/or mobile applications. It provides elementary services (user registration & management, data storage, file storage, queues) and retrieval features (full text search, geolocation search, joins) to power common app features.

+ +

It is a multi-tenant system designed for deployment to public cloud environments (such as Amazon Web Services, Rackspace, etc.) or to run on traditional server infrastructures so that anyone can run their own private BaaS deployment.

+ +

For architects and back-end teams, it aims to provide a distributed, easily extendable, operationally predictable and highly scalable solution. For front-end developers, it aims to simplify the development process by enabling them to rapidly build and operate mobile and web applications without requiring backend expertise.

+
+ +
+ +
+ + + + + + + + + + + + + + + diff --git a/content/js/bootstrap.min.js b/content/js/bootstrap.min.js new file mode 100644 index 0000000000..31372852dd --- /dev/null +++ b/content/js/bootstrap.min.js @@ -0,0 +1,8 @@ +/** +* Bootstrap v3.0.0 by @fat and @mdo +* Copyright 2013 Twitter Inc. +* Licensed under http://www.apache.org/licenses/LICENSE-2.0. +* +* Designed and built with all the love in the world by @mdo and @fat. +*/ +if(!jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(window.jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(window.jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery); \ No newline at end of file diff --git a/content/js/head.js b/content/js/head.js new file mode 100644 index 0000000000..aa15cb8254 --- /dev/null +++ b/content/js/head.js @@ -0,0 +1,708 @@ +// // the most simple case. load and execute single script without blocking. +// head.js("/path/to/file.js"); + +// // load a script and execute a function after it has been loaded +// head.js("/path/to/file.js", function() { + +// }); + +// // load files in parallel but execute them in sequence +// head.js("file1.js", "file2.js", ... "fileN.js"); + +// // execute function after all scripts have been loaded +// head.js("file1.js", "file2.js", function() { + +// }); + +// // files are loaded in parallel and executed in order they arrive +// head.js("file1.js"); +// head.js("file2.js"); +// head.js("file3.js"); + +// // the previous can also be written as +// head.js("file1.js").js("file1.js").js("file3.js"); + + + + + +/** + Head JS The only script in your + Copyright Tero Piirainen (tipiirai) + License MIT / http://bit.ly/mit-license + Version 0.96 + + http://headjs.com +*/ +(function(doc) { + + var html = doc.documentElement, + conf = { + screens: [320, 480, 640, 768, 1024, 1280, 1440, 1680, 1920], + section: "-section", + page: "-page", + head: "head" + }, + klass = []; + + + if (window.head_conf) { + for (var key in head_conf) { + if (head_conf[key] !== undefined) { + conf[key] = head_conf[key]; + } + } + } + + function pushClass(name) { + klass[klass.length] = name; + } + + function removeClass(name) { + var re = new RegExp("\\b" + name + "\\b"); + html.className = html.className.replace(re, ''); + } + + function each(arr, fn) { + for (var i = 0, arr_length = arr.length; i < arr_length; i++) { + fn.call(arr, arr[i], i); + } + } + + // API + var api = window[conf.head] = function() { + api.ready.apply(null, arguments); + }; + + api.feature = function(key, enabled, queue) { + + // internal: apply all classes + if (!key) { + html.className += ' ' + klass.join( ' ' ); + klass = []; + return; + } + + if (Object.prototype.toString.call(enabled) == '[object Function]') { + enabled = enabled.call(); + } + + pushClass((enabled ? '' : 'no-') + key); + api[key] = !!enabled; + + // apply class to HTML element + if (!queue) { + removeClass('no-' + key); + removeClass(key); + api.feature(); + } + + return api; + }; + + // browser type & version + var ua = navigator.userAgent.toLowerCase(); + + ua = /(webkit)[ \/]([\w.]+)/.exec( ua ) || + /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) || + /(msie) ([\w.]+)/.exec( ua ) || + !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) || []; + + + if (ua[1] == 'msie') { + ua[1] = 'ie'; + ua[2] = document.documentMode || ua[2]; + } + + pushClass(ua[1]); + + api.browser = { version: ua[2] }; + api.browser[ua[1]] = true; + + // IE specific + if (api.browser.ie) { + + pushClass("ie" + parseFloat(ua[2])); + + // IE versions + for (var ver = 3; ver < 11; ver++) { + if (parseFloat(ua[2]) < ver) { pushClass("lt-ie" + ver); } + } + + // HTML5 support + each("abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video".split("|"), function(el) { + doc.createElement(el); + }); + + } + + + // CSS "router" + each(location.pathname.split("/"), function(el, i) { + + if (this.length > 2 && this[i + 1] !== undefined) { + if (i) { pushClass(this.slice(1, i+1).join("-") + conf.section); } + + } else { + + // pageId + var id = el || "index", index = id.indexOf("."); + if (index > 0) { id = id.substring(0, index); } + html.id = id + conf.page; + + // on root? + if (!i) { pushClass("root" + conf.section); } + } + }); + + + // screen resolution: w-100, lt-480, lt-1024 ... + function screenSize() { + var w = window.outerWidth || html.clientWidth; + + // remove earlier widths + html.className = html.className.replace(/ (w|lt)-\d+/g, ""); + + // add new ones + pushClass("w-" + Math.round(w / 100) * 100); + + each(conf.screens, function(width) { + if (w <= width) { pushClass("lt-" + width); } + }); + + api.feature(); + } + + screenSize(); + window.onresize = screenSize; + + api.feature("js", true).feature(); + +})(document); + + +/** + Head JS The only script in your + Copyright Tero Piirainen (tipiirai) + License MIT / http://bit.ly/mit-license + Version 0.96 + + http://headjs.com +*/ +(function() { + /* + To add a new test: + + head.feature("video", function() { + var tag = document.createElement('video'); + return !!tag.canPlayType; + }); + + Good place to grab more tests + + https://github.com/Modernizr/Modernizr/blob/master/modernizr.js + */ + + + /* CSS modernizer */ + var el = document.createElement("i"), + style = el.style, + prefs = ' -o- -moz- -ms- -webkit- -khtml- '.split(' '), + domPrefs = 'Webkit Moz O ms Khtml'.split(' '), + + head_var = window.head_conf && head_conf.head || "head", + api = window[head_var]; + + + // Thanks Paul Irish! + function testProps(props) { + for (var i in props) { + if (style[props[i]] !== undefined) { + return true; + } + } + } + + + function testAll(prop) { + var camel = prop.charAt(0).toUpperCase() + prop.substr(1), + props = (prop + ' ' + domPrefs.join(camel + ' ') + camel).split(' '); + + return !!testProps(props); + } + + var tests = { + + gradient: function() { + var s1 = 'background-image:', + s2 = 'gradient(linear,left top,right bottom,from(#9f9),to(#fff));', + s3 = 'linear-gradient(left top,#eee,#fff);'; + + style.cssText = (s1 + prefs.join(s2 + s1) + prefs.join(s3 + s1)).slice(0,-s1.length); + return !!style.backgroundImage; + }, + + rgba: function() { + style.cssText = "background-color:rgba(0,0,0,0.5)"; + return !!style.backgroundColor; + }, + + opacity: function() { + return el.style.opacity === ""; + }, + + textshadow: function() { + return style.textShadow === ''; + }, + + multiplebgs: function() { + style.cssText = "background:url(//:),url(//:),red url(//:)"; + return new RegExp("(url\\s*\\(.*?){3}").test(style.background); + }, + + boxshadow: function() { + return testAll("boxShadow"); + }, + + borderimage: function() { + return testAll("borderImage"); + }, + + borderradius: function() { + return testAll("borderRadius"); + }, + + cssreflections: function() { + return testAll("boxReflect"); + }, + + csstransforms: function() { + return testAll("transform"); + }, + + csstransitions: function() { + return testAll("transition"); + }, + + /* + font-face support. Uses browser sniffing but is synchronous. + + http://paulirish.com/2009/font-face-feature-detection/ + */ + fontface: function() { + var ua = navigator.userAgent, parsed; + + if (/*@cc_on@if(@_jscript_version>=5)!@end@*/0) + return true; + + if (parsed = ua.match(/Chrome\/(\d+\.\d+\.\d+\.\d+)/)) + return parsed[1] >= '4.0.249.4' || 1 * parsed[1].split(".")[0] > 5; + if ((parsed = ua.match(/Safari\/(\d+\.\d+)/)) && !/iPhone/.test(ua)) + return parsed[1] >= '525.13'; + if (/Opera/.test({}.toString.call(window.opera))) + return opera.version() >= '10.00'; + if (parsed = ua.match(/rv:(\d+\.\d+\.\d+)[^b].*Gecko\//)) + return parsed[1] >= '1.9.1'; + + return false; + } + }; + + // queue features + for (var key in tests) { + if (tests[key]) { + api.feature(key, tests[key].call(), true); + } + } + + // enable features at once + api.feature(); + +})(); + + +/** + Head JS The only script in your + Copyright Tero Piirainen (tipiirai) + License MIT / http://bit.ly/mit-license + Version 0.96 + + http://headjs.com +*/ +(function(doc) { + + var head = doc.documentElement, + isHeadReady, + isDomReady, + domWaiters = [], + queue = [], // waiters for the "head ready" event + handlers = {}, // user functions waiting for events + scripts = {}, // loadable scripts in different states + isAsync = doc.createElement("script").async === true || "MozAppearance" in doc.documentElement.style || window.opera; + + + /*** public API ***/ + var head_var = window.head_conf && head_conf.head || "head", + api = window[head_var] = (window[head_var] || function() { api.ready.apply(null, arguments); }); + + // states + var PRELOADED = 1, + PRELOADING = 2, + LOADING = 3, + LOADED = 4; + + + // Method 1: simply load and let browser take care of ordering + if (isAsync) { + + api.js = function() { + + var args = arguments, + fn = args[args.length -1], + els = {}; + + if (!isFunc(fn)) { fn = null; } + + each(args, function(el, i) { + + if (el != fn) { + el = getScript(el); + els[el.name] = el; + + load(el, fn && i == args.length -2 ? function() { + if (allLoaded(els)) { one(fn); } + + } : null); + } + }); + + return api; + }; + + + // Method 2: preload with text/cache hack + } else { + + api.js = function() { + + var args = arguments, + rest = [].slice.call(args, 1), + next = rest[0]; + + // wait for a while. immediate execution causes some browsers to ignore caching + if (!isHeadReady) { + queue.push(function() { + api.js.apply(null, args); + }); + return api; + } + + // multiple arguments + if (next) { + + // load + each(rest, function(el) { + if (!isFunc(el)) { + preload(getScript(el)); + } + }); + + // execute + load(getScript(args[0]), isFunc(next) ? next : function() { + api.js.apply(null, rest); + }); + + + // single script + } else { + load(getScript(args[0])); + } + + return api; + }; + } + + api.ready = function(key, fn) { + + // DOM ready check: head.ready(document, function() { }); + if (key == doc) { + if (isDomReady) { one(fn); } + else { domWaiters.push(fn); } + return api; + } + + // shift arguments + if (isFunc(key)) { + fn = key; + key = "ALL"; + } + + // make sure arguments are sane + if (typeof key != 'string' || !isFunc(fn)) { return api; } + + var script = scripts[key]; + + // script already loaded --> execute and return + if (script && script.state == LOADED || key == 'ALL' && allLoaded() && isDomReady) { + one(fn); + return api; + } + + var arr = handlers[key]; + if (!arr) { arr = handlers[key] = [fn]; } + else { arr.push(fn); } + return api; + }; + + + // perform this when DOM is ready + api.ready(doc, function() { + + if (allLoaded()) { + each(handlers.ALL, function(fn) { + one(fn); + }); + } + + if (api.feature) { + api.feature("domloaded", true); + } + }); + + + /*** private functions ***/ + + + // call function once + function one(fn) { + if (fn._done) { return; } + fn(); + fn._done = 1; + } + + + function toLabel(url) { + var els = url.split("/"), + name = els[els.length -1], + i = name.indexOf("?"); + + return i != -1 ? name.substring(0, i) : name; + } + + + function getScript(url) { + + var script; + + if (typeof url == 'object') { + for (var key in url) { + if (url[key]) { + script = { name: key, url: url[key] }; + } + } + } else { + script = { name: toLabel(url), url: url }; + } + + var existing = scripts[script.name]; + if (existing && existing.url === script.url) { return existing; } + + scripts[script.name] = script; + return script; + } + + + function each(arr, fn) { + if (!arr) { return; } + + // arguments special type + if (typeof arr == 'object') { arr = [].slice.call(arr); } + + // do the job + for (var i = 0; i < arr.length; i++) { + fn.call(arr, arr[i], i); + } + } + + function isFunc(el) { + return Object.prototype.toString.call(el) == '[object Function]'; + } + + function allLoaded(els) { + + els = els || scripts; + + var loaded; + + for (var name in els) { + if (els.hasOwnProperty(name) && els[name].state != LOADED) { return false; } + loaded = true; + } + + return loaded; + } + + + function onPreload(script) { + script.state = PRELOADED; + + each(script.onpreload, function(el) { + el.call(); + }); + } + + function preload(script, callback) { + + if (script.state === undefined) { + + script.state = PRELOADING; + script.onpreload = []; + + scriptTag({ src: script.url, type: 'cache'}, function() { + onPreload(script); + }); + } + } + + function load(script, callback) { + + if (script.state == LOADED) { + return callback && callback(); + } + + if (script.state == LOADING) { + return api.ready(script.name, callback); + } + + if (script.state == PRELOADING) { + return script.onpreload.push(function() { + load(script, callback); + }); + } + + script.state = LOADING; + + scriptTag(script.url, function() { + + script.state = LOADED; + + if (callback) { callback(); } + + // handlers for this script + each(handlers[script.name], function(fn) { + one(fn); + }); + + // everything ready + if (allLoaded() && isDomReady) { + each(handlers.ALL, function(fn) { + one(fn); + }); + } + }); + } + + + function scriptTag(src, callback) { + + var s = doc.createElement('script'); + s.type = 'text/' + (src.type || 'javascript'); + s.src = src.src || src; + s.async = false; + + s.onreadystatechange = s.onload = function() { + + var state = s.readyState; + + if (!callback.done && (!state || /loaded|complete/.test(state))) { + callback.done = true; + callback(); + } + }; + + // use body if available. more safe in IE + (doc.body || head).appendChild(s); + } + + /* + The much desired DOM ready check + Thanks to jQuery and http://javascript.nwbox.com/IEContentLoaded/ + */ + + function fireReady() { + if (!isDomReady) { + isDomReady = true; + each(domWaiters, function(fn) { + one(fn); + }); + } + } + + // W3C + if (window.addEventListener) { + doc.addEventListener("DOMContentLoaded", fireReady, false); + + // fallback. this is always called + window.addEventListener("load", fireReady, false); + + // IE + } else if (window.attachEvent) { + + // for iframes + doc.attachEvent("onreadystatechange", function() { + if (doc.readyState === "complete" ) { + fireReady(); + } + }); + + + // avoid frames with different domains issue + var frameElement = 1; + + try { + frameElement = window.frameElement; + + } catch(e) {} + + + if (!frameElement && head.doScroll) { + + (function() { + try { + head.doScroll("left"); + fireReady(); + + } catch(e) { + setTimeout(arguments.callee, 1); + return; + } + })(); + } + + // fallback + window.attachEvent("onload", fireReady); + } + + + // enable document.readyState for Firefox <= 3.5 + if (!doc.readyState && doc.addEventListener) { + doc.readyState = "loading"; + doc.addEventListener("DOMContentLoaded", handler = function () { + doc.removeEventListener("DOMContentLoaded", handler, false); + doc.readyState = "complete"; + }, false); + } + + /* + We wait for 300 ms before script loading starts. for some reason this is needed + to make sure scripts are cached. Not sure why this happens yet. A case study: + + https://github.com/headjs/headjs/issues/closed#issue/83 + */ + setTimeout(function() { + isHeadReady = true; + each(queue, function(fn) { fn(); }); + + }, 300); + +})(document); diff --git a/content/js/html5shiv.js b/content/js/html5shiv.js new file mode 100644 index 0000000000..784f221caf --- /dev/null +++ b/content/js/html5shiv.js @@ -0,0 +1,8 @@ +/* + HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +*/ +(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); +a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; +c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| +"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",version:"3.6.2pre",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); +for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=lt(),k=lt(),E=lt(),S=!1,A=function(){return 0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=bt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+xt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return At(e.replace(z,"$1"),t,n,i)}function st(e){return K.test(e+"")}function lt(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function ut(e){return e[b]=!0,e}function ct(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function pt(e,t,n){e=e.split("|");var r,i=e.length,a=n?null:t;while(i--)(r=o.attrHandle[e[i]])&&r!==t||(o.attrHandle[e[i]]=a)}function ft(e,t){var n=e.getAttributeNode(t);return n&&n.specified?n.value:e[t]===!0?t.toLowerCase():null}function dt(e,t){return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}function ht(e){return"input"===e.nodeName.toLowerCase()?e.defaultValue:t}function gt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function mt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function yt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function vt(e){return ut(function(t){return t=+t,ut(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.parentWindow;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.frameElement&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ct(function(e){return e.innerHTML="",pt("type|href|height|width",dt,"#"===e.firstChild.getAttribute("href")),pt(B,ft,null==e.getAttribute("disabled")),e.className="i",!e.getAttribute("className")}),r.input=ct(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")}),pt("value",ht,r.attributes&&r.input),r.getElementsByTagName=ct(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ct(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ct(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=st(n.querySelectorAll))&&(ct(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ct(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=st(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ct(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=st(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},r.sortDetached=ct(function(e){return 1&e.compareDocumentPosition(n.createElement("div"))}),A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return gt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?gt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:ut,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=bt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?ut(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ut(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?ut(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ut(function(e){return function(t){return at(e,t).length>0}}),contains:ut(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:ut(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:vt(function(){return[0]}),last:vt(function(e,t){return[t-1]}),eq:vt(function(e,t,n){return[0>n?n+t:n]}),even:vt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:vt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:vt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:vt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=mt(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=yt(n);function bt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function xt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function wt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function Tt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function Ct(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function Nt(e,t,n,r,i,o){return r&&!r[b]&&(r=Nt(r)),i&&!i[b]&&(i=Nt(i,o)),ut(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||St(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:Ct(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=Ct(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=Ct(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function kt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=wt(function(e){return e===t},s,!0),p=wt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[wt(Tt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return Nt(l>1&&Tt(f),l>1&&xt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&kt(e.slice(l,r)),i>r&&kt(e=e.slice(r)),i>r&&xt(e))}f.push(n)}return Tt(f)}function Et(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=Ct(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?ut(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=bt(e)),n=t.length;while(n--)o=kt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Et(i,r))}return o};function St(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function At(e,t,n,i){var a,s,u,c,p,f=bt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&xt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}o.pseudos.nth=o.pseudos.eq;function jt(){}jt.prototype=o.filters=o.pseudos,o.setFilters=new jt,r.sortStable=b.split("").sort(A).join("")===b,p(),[0,0].sort(A),r.detectDuplicates=S,x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!l||i&&!u||(n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
t
",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null) +}),n=s=l=u=r=o=null,t}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=x(this),l=t,u=e.match(T)||[];while(o=u[a++])l=r?l:!s.hasClass(o),s[l?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
","
"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); +u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x(" + + +
+ +
+
+ +
+ +
+
+
+
+ +

Hover your cursor over the '(?)' icons to get helpful tips and information.

+
+ + + + + +
+ {{alert.msg}} +
+ + + +
+ +
+
+

© Apache Usergrid 2015

+
+
+
+
+
+ + + + + + + + + + diff --git a/content/v101-portal-demo/index-template.html b/content/v101-portal-demo/index-template.html new file mode 100644 index 0000000000..d884685dd5 --- /dev/null +++ b/content/v101-portal-demo/index-template.html @@ -0,0 +1,156 @@ + + + + + + + Usergrid Admin Portal + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ +
+
+
+
+ +

Hover your cursor over the '(?)' icons to get helpful tips and information.

+
+ + + + + +
+ {{alert.msg}} +
+ + + +
+ +
+
+

© Apache Usergrid 2015

+
+
+
+
+
+ + + + + + + + + + diff --git a/content/v101-portal-demo/index.html b/content/v101-portal-demo/index.html new file mode 100644 index 0000000000..6930ebf87f --- /dev/null +++ b/content/v101-portal-demo/index.html @@ -0,0 +1,151 @@ + + + + + + + Usergrid Admin Portal + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ +
+
+
+
+ +

Hover your cursor over the '(?)' icons to get helpful tips and information.

+
+ + + + + +
+ {{alert.msg}} +
+ + + +
+ +
+
+

© Apache Usergrid 2015

+
+
+
+
+
+ + + + + + + + + + diff --git a/content/v101-portal-demo/js/generated/usergrid-dev.js b/content/v101-portal-demo/js/generated/usergrid-dev.js new file mode 100644 index 0000000000..0dfacc58e0 --- /dev/null +++ b/content/v101-portal-demo/js/generated/usergrid-dev.js @@ -0,0 +1,4886 @@ + /** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + + /*! usergrid@2.0.18 */ +(function(exports, global) { + global["true"] = exports; + "use strict"; + var polyfills = function(window, Object) { + window.requestAnimFrame = function() { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback, element) { + window.setTimeout(callback, 1e3 / 60); + }; + }(); + Object.defineProperty(Object.prototype, "clone", { + enumerable: false, + writable: true, + value: function() { + var i, newObj = this instanceof Array ? [] : {}; + for (i in this) { + if (i === "clone") { + continue; + } + if (this[i] && typeof this[i] === "object") { + newObj[i] = this[i].clone(); + } else { + newObj[i] = this[i]; + } + } + return newObj; + } + }); + Object.defineProperty(Object.prototype, "stringifyJSON", { + enumerable: false, + writable: true, + value: function() { + return JSON.stringify(this, null, " "); + } + }); + }; + polyfills(window, Object); + var global = global || this; + var AppServices = AppServices || {}; + global.AppServices = global.AppServices || AppServices; + AppServices.Constants = angular.module("appservices.constants", []); + AppServices.Services = angular.module("appservices.services", []); + AppServices.Controllers = angular.module("appservices.controllers", []); + AppServices.Filters = angular.module("appservices.filters", []); + AppServices.Directives = angular.module("appservices.directives", []); + angular.module("appservices", [ "ngRoute", "ngResource", "ngSanitize", "ui.bootstrap", "appservices.filters", "appservices.services", "appservices.directives", "appservices.constants", "appservices.controllers", "angular-intro" ]).config([ "$routeProvider", "$locationProvider", "$sceDelegateProvider", "$httpProvider", function($routeProvider, $locationProvider, $sceDelegateProvider, $httpProvider) { + $routeProvider.when("/org-overview", { + templateUrl: "org-overview/org-overview.html", + controller: "OrgOverviewCtrl" + }).when("/login", { + templateUrl: "login/login.html", + controller: "LoginCtrl" + }).when("/login/loading", { + templateUrl: "login/loading.html", + controller: "LoginCtrl" + }).when("/app-overview/summary", { + templateUrl: "app-overview/app-overview.html", + controller: "AppOverviewCtrl" + }).when("/forgot-password", { + templateUrl: "login/forgot-password.html", + controller: "ForgotPasswordCtrl" + }).when("/register", { + templateUrl: "login/register.html", + controller: "RegisterCtrl" + }).when("/users", { + templateUrl: "users/users.html", + controller: "UsersCtrl" + }).when("/users/profile", { + templateUrl: "users/users-profile.html", + controller: "UsersProfileCtrl" + }).when("/users/groups", { + templateUrl: "users/users-groups.html", + controller: "UsersGroupsCtrl" + }).when("/users/activities", { + templateUrl: "users/users-activities.html", + controller: "UsersActivitiesCtrl" + }).when("/users/feed", { + templateUrl: "users/users-feed.html", + controller: "UsersFeedCtrl" + }).when("/users/graph", { + templateUrl: "users/users-graph.html", + controller: "UsersGraphCtrl" + }).when("/users/roles", { + templateUrl: "users/users-roles.html", + controller: "UsersRolesCtrl" + }).when("/groups", { + templateUrl: "groups/groups.html", + controller: "GroupsCtrl" + }).when("/groups/details", { + templateUrl: "groups/groups-details.html", + controller: "GroupsDetailsCtrl" + }).when("/groups/members", { + templateUrl: "groups/groups-members.html", + controller: "GroupsMembersCtrl" + }).when("/groups/activities", { + templateUrl: "groups/groups-activities.html", + controller: "GroupsActivitiesCtrl" + }).when("/groups/roles", { + templateUrl: "groups/groups-roles.html", + controller: "GroupsRolesCtrl" + }).when("/roles", { + templateUrl: "roles/roles.html", + controller: "RolesCtrl" + }).when("/roles/settings", { + templateUrl: "roles/roles-settings.html", + controller: "RolesSettingsCtrl" + }).when("/roles/users", { + templateUrl: "roles/roles-users.html", + controller: "RolesUsersCtrl" + }).when("/roles/groups", { + templateUrl: "roles/roles-groups.html", + controller: "RolesGroupsCtrl" + }).when("/data", { + templateUrl: "data/data.html", + controller: "DataCtrl" + }).when("/data/entity", { + templateUrl: "data/entity.html", + controller: "EntityCtrl" + }).when("/data/shell", { + templateUrl: "data/shell.html", + controller: "ShellCtrl" + }).when("/organizations", { + templateUrl: "profile/organizations.html", + controller: "OrgCtrl" + }).when("/profile", { + templateUrl: "profile/profile.html", + controller: "ProfileCtrl" + }).when("/activities", { + templateUrl: "activities/activities.html", + controller: "ActivitiesCtrl" + }).when("/shell", { + templateUrl: "shell/shell.html", + controller: "ShellCtrl" + }).when("/logout", { + templateUrl: "login/logout.html", + controller: "LogoutCtrl" + }).when("/push/sendNotification", { + templateUrl: "push/push-send-notification.html", + controller: "PushSendNotificationCtrl" + }).when("/push/getStarted", { + templateUrl: "push/push-get-started.html", + controller: "PushGetStartedCtrl" + }).when("/push/history", { + templateUrl: "push/push-history.html", + controller: "PushHistoryCtrl" + }).when("/push/history/receipts", { + templateUrl: "push/push-receipts.html", + controller: "PushReceiptsCtrl" + }).when("/push/configuration", { + templateUrl: "push/push-config.html", + controller: "PushConfigCtrl" + }).otherwise({ + redirectTo: "/org-overview" + }); + $locationProvider.html5Mode(false).hashPrefix("!"); + $sceDelegateProvider.resourceUrlWhitelist([ "self", "https://api.usergrid.com/**" ]); + $httpProvider.defaults.useXDomain = true; + } ]); + "use strict"; + AppServices.Controllers.controller("ActivitiesCtrl", [ "ug", "$scope", "$rootScope", "$location", "$route", function(ug, $scope, $rootScope, $location, $route) { + $scope.$on("app-activities-received", function(evt, data) { + $scope.activities = data; + $scope.$apply(); + }); + $scope.$on("app-activities-error", function(evt, data) { + $rootScope.$broadcast("alert", "error", "Application failed to retreive activities data."); + }); + ug.getActivities(); + } ]); + "use strict"; + AppServices.Controllers.controller("AppOverviewCtrl", [ "ug", "$scope", "$rootScope", "$log", function(ug, $scope, $rootScope, $log) { + $scope.appOverview = {}; + $scope.collections = []; + $scope.graph = ""; + $scope.$on("top-collections-received", function(event, collections) { + $scope.collections = collections; + $scope.applyScope(); + }); + ug.getTopCollections(); + } ]); + "use strict"; + AppServices.Controllers.controller("DataCtrl", [ "ug", "$scope", "$rootScope", "$location", function(ug, $scope, $rootScope, $location) { + var init = function() { + $scope.verb = "GET"; + $scope.display = ""; + $scope.queryBodyDetail = {}; + $scope.queryBodyDisplay = "none"; + $scope.queryLimitDisplay = "block"; + $scope.queryStringDisplay = "block"; + $scope.entitySelected = {}; + $scope.newCollection = { + name: "", + entity: '{"name":"test"}' + }; + $rootScope.queryCollection = {}; + $scope.data = {}; + $scope.data.queryPath = ""; + $scope.data.queryBody = '{ "name":"value" }'; + $scope.data.searchString = ""; + $scope.data.queryLimit = ""; + }; + var runQuery = function(verb) { + $scope.loading = true; + var queryPath = $scope.removeFirstSlash($scope.data.queryPath || ""); + var searchString = $scope.data.searchString || ""; + var queryLimit = $scope.data.queryLimit || ""; + var body = JSON.parse($scope.data.queryBody || "{}"); + if (verb == "POST" && $scope.validateJson(true)) { + ug.runDataPOSTQuery(queryPath, body); + } else if (verb == "PUT" && $scope.validateJson(true)) { + ug.runDataPutQuery(queryPath, searchString, queryLimit, body); + } else if (verb == "DELETE") { + ug.runDataDeleteQuery(queryPath, searchString, queryLimit); + } else { + ug.runDataQuery(queryPath, searchString, queryLimit); + } + }; + $scope.$on("top-collections-received", function(event, collectionList) { + $scope.loading = false; + var ignoredCollections = [ "events" ]; + ignoredCollections.forEach(function(ignoredCollection) { + collectionList.hasOwnProperty(ignoredCollection) && delete collectionList[ignoredCollection]; + }); + $scope.collectionList = collectionList; + $scope.queryBoxesSelected = false; + if (!$scope.queryPath) { + $scope.loadCollection("/" + $scope.collectionList[Object.keys($scope.collectionList).sort()[0]].name); + } + $scope.applyScope(); + }); + $scope.$on("error-running-query", function(event) { + $scope.loading = false; + runQuery("GET"); + $scope.applyScope(); + }); + $scope.$on("entity-deleted", function(event) { + $scope.deleteLoading = false; + $rootScope.$broadcast("alert", "success", "Entities deleted sucessfully"); + $scope.queryBoxesSelected = false; + $scope.checkNextPrev(); + $scope.applyScope(); + }); + $scope.$on("entity-deleted-error", function(event) { + $scope.deleteLoading = false; + runQuery("GET"); + $scope.applyScope(); + }); + $scope.$on("collection-created", function() { + $scope.newCollection.name = ""; + $scope.newCollection.entity = '{ "name":"value" }'; + }); + $scope.$on("query-received", function(event, collection) { + $scope.loading = false; + $rootScope.queryCollection = collection; + ug.getIndexes($scope.data.queryPath); + $scope.setDisplayType(); + $scope.checkNextPrev(); + $scope.applyScope(); + $scope.queryBoxesSelected = false; + }); + $scope.$on("query-error", function(event) { + $scope.loading = false; + $scope.applyScope(); + $scope.queryBoxesSelected = false; + }); + $scope.$on("indexes-received", function(event, indexes) { + var fred = indexes; + }); + $scope.$on("app-changed", function() { + init(); + }); + $scope.setDisplayType = function() { + $scope.display = "generic"; + }; + $scope.deleteEntitiesDialog = function(modalId) { + $scope.deleteLoading = false; + $scope.deleteEntities($rootScope.queryCollection, "entity-deleted", "error deleting entity"); + $scope.hideModal(modalId); + }; + $scope.newCollectionDialog = function(modalId) { + if ($scope.newCollection.name) { + ug.createCollection($scope.newCollection.name); + ug.getTopCollections(); + $rootScope.$broadcast("alert", "success", "Collection created successfully."); + $scope.hideModal(modalId); + } else { + $rootScope.$broadcast("alert", "error", "You must specify a collection name."); + } + }; + $scope.newCollectionWithEntityDialog = function(modalId) { + if (!($scope.newCollection.name && $scope.newCollection.name.length > 0)) { + $rootScope.$broadcast("alert", "error", "You must specify a collection name."); + } else if (!($scope.newCollection.entity && $scope.newCollection.entity.length > 0)) { + $rootScope.$broadcast("alert", "error", "You must specify JSON data for the new entity."); + } else if (!$scope.validateEntityData(true)) {} else { + ug.createCollectionWithEntity($scope.newCollection.name, $scope.newCollection.entity); + ug.getTopCollections(); + $scope.hideModal(modalId); + } + }; + $scope.addToPath = function(uuid) { + $scope.data.queryPath = "/" + $rootScope.queryCollection._type + "/" + uuid; + }; + $scope.removeFromPath = function() { + $scope.data.queryPath = "/" + $rootScope.queryCollection._type; + }; + $scope.isDeep = function(item) { + return Object.prototype.toString.call(item) === "[object Object]"; + }; + $scope.loadCollection = function(type) { + $scope.data.queryPath = "/" + type.substring(1, type.length); + $scope.data.searchString = ""; + $scope.data.queryLimit = ""; + $scope.data.body = '{ "name":"value" }'; + $scope.selectGET(); + $scope.applyScope(); + $scope.run(); + }; + $scope.selectGET = function() { + $scope.queryBodyDisplay = "none"; + $scope.queryLimitDisplay = "block"; + $scope.queryStringDisplay = "block"; + $scope.verb = "GET"; + }; + $scope.selectPOST = function() { + $scope.queryBodyDisplay = "block"; + $scope.queryLimitDisplay = "none"; + $scope.queryStringDisplay = "none"; + $scope.verb = "POST"; + }; + $scope.selectPUT = function() { + $scope.queryBodyDisplay = "block"; + $scope.queryLimitDisplay = "block"; + $scope.queryStringDisplay = "block"; + $scope.verb = "PUT"; + }; + $scope.selectDELETE = function() { + $scope.queryBodyDisplay = "none"; + $scope.queryLimitDisplay = "block"; + $scope.queryStringDisplay = "block"; + $scope.verb = "DELETE"; + }; + $scope.validateEntityData = function(skipMessage) { + var queryBody = $scope.newCollection.entity; + try { + queryBody = JSON.parse(queryBody); + } catch (e) { + $rootScope.$broadcast("alert", "error", "JSON is not valid"); + return false; + } + queryBody = JSON.stringify(queryBody, null, 2); + !skipMessage && $rootScope.$broadcast("alert", "success", "JSON is valid"); + $scope.newCollection.entity = queryBody; + return true; + }; + $scope.validateJson = function(skipMessage) { + var queryBody = $scope.data.queryBody; + try { + queryBody = JSON.parse(queryBody); + } catch (e) { + $rootScope.$broadcast("alert", "error", "JSON is not valid"); + return false; + } + queryBody = JSON.stringify(queryBody, null, 2); + !skipMessage && $rootScope.$broadcast("alert", "success", "JSON is valid"); + $scope.data.queryBody = queryBody; + return true; + }; + $scope.isValidJSON = function(data) { + try { + data = JSON.parse(data); + } catch (e) { + return false; + } + return true; + }; + $scope.formatJSON = function(data) { + try { + data = JSON.parse(data); + } catch (e) { + return data; + } + return JSON.stringify(data, null, 2); + }; + $scope.saveEntity = function(entity) { + if (!$scope.validateJson()) { + return false; + } + var queryBody = entity._json; + queryBody = JSON.parse(queryBody); + $rootScope.selectedEntity.set(); + $rootScope.selectedEntity.set(queryBody); + $rootScope.selectedEntity.set("type", entity._data.type); + $rootScope.selectedEntity.set("uuid", entity._data.uuid); + $rootScope.selectedEntity.save(function(err, data) { + if (err) { + $rootScope.$broadcast("alert", "error", "error: " + data.error_description); + } else { + $rootScope.$broadcast("alert", "success", "entity saved"); + } + }); + }; + $scope.run = function() { + $rootScope.queryCollection = ""; + var verb = $scope.verb; + runQuery(verb); + }; + $scope.hasProperty = function(prop) { + var retval = false; + if (typeof $rootScope.queryCollection._list !== "undefined") { + angular.forEach($rootScope.queryCollection._list, function(value, key) { + if (!retval) { + if (value._data[prop]) { + retval = true; + } + } + }); + } + return retval; + }; + $scope.resetNextPrev = function() { + $scope.previous_display = "none"; + $scope.next_display = "none"; + }; + $scope.checkNextPrev = function() { + $scope.resetNextPrev(); + if ($rootScope.queryCollection.hasPreviousPage()) { + $scope.previous_display = "default"; + } + if ($rootScope.queryCollection.hasNextPage()) { + $scope.next_display = "default"; + } + }; + $scope.selectEntity = function(uuid, addToPath) { + $rootScope.selectedEntity = $rootScope.queryCollection.getEntityByUUID(uuid); + if (addToPath) { + $scope.addToPath(uuid); + } else { + $scope.removeFromPath(); + } + }; + $scope.getJSONView = function(entity) { + var tempjson = entity.get(); + var queryBody = JSON.stringify(tempjson, null, 2); + queryBody = JSON.parse(queryBody); + delete queryBody.metadata; + delete queryBody.uuid; + delete queryBody.created; + delete queryBody.modified; + delete queryBody.type; + $scope.queryBody = JSON.stringify(queryBody, null, 2); + }; + $scope.getPrevious = function() { + $rootScope.queryCollection.getPreviousPage(function(err) { + if (err) { + $rootScope.$broadcast("alert", "error", "error getting previous page of data"); + } + $scope.checkNextPrev(); + $scope.applyScope(); + }); + }; + $scope.getNext = function() { + $rootScope.queryCollection.getNextPage(function(err) { + if (err) { + $rootScope.$broadcast("alert", "error", "error getting next page of data"); + } + $scope.checkNextPrev(); + $scope.applyScope(); + }); + }; + init(); + $rootScope.queryCollection = $rootScope.queryCollection || {}; + $rootScope.selectedEntity = {}; + if ($rootScope.queryCollection && $rootScope.queryCollection._type) { + $scope.loadCollection($rootScope.queryCollection._type); + $scope.setDisplayType(); + } + ug.getTopCollections(); + $scope.resetNextPrev(); + } ]); + "use strict"; + AppServices.Controllers.controller("EntityCtrl", [ "ug", "$scope", "$rootScope", "$location", function(ug, $scope, $rootScope, $location) { + if (!$rootScope.selectedEntity) { + $location.path("/data"); + return; + } + $scope.entityUUID = $rootScope.selectedEntity.get("uuid"); + $scope.entityType = $rootScope.selectedEntity.get("type"); + var tempjson = $rootScope.selectedEntity.get(); + var queryBody = JSON.stringify(tempjson, null, 2); + queryBody = JSON.parse(queryBody); + delete queryBody.metadata; + delete queryBody.uuid; + delete queryBody.created; + delete queryBody.modified; + delete queryBody.type; + $scope.queryBody = JSON.stringify(queryBody, null, 2); + $scope.validateJson = function() { + var queryBody = $scope.queryBody; + try { + queryBody = JSON.parse(queryBody); + } catch (e) { + $rootScope.$broadcast("alert", "error", "JSON is not valid"); + return false; + } + queryBody = JSON.stringify(queryBody, null, 2); + $rootScope.$broadcast("alert", "success", "JSON is valid"); + $scope.queryBody = queryBody; + return true; + }; + $scope.saveEntity = function() { + if (!$scope.validateJson()) { + return false; + } + var queryBody = $scope.queryBody; + queryBody = JSON.parse(queryBody); + $rootScope.selectedEntity.set(); + $rootScope.selectedEntity.set(queryBody); + $rootScope.selectedEntity.set("type", $scope.entityType); + $rootScope.selectedEntity.set("uuid", $scope.entityUUID); + $rootScope.selectedEntity.save(function(err, data) { + if (err) { + $rootScope.$broadcast("alert", "error", "error: " + data.error_description); + } else { + $rootScope.$broadcast("alert", "success", "entity saved"); + } + }); + }; + } ]); + "use strict"; + AppServices.Directives.directive("balloon", [ "$window", "$timeout", function($window, $timeout) { + return { + restrict: "ECA", + scope: "=", + template: "" + '
' + "
", + replace: true, + transclude: true, + link: function linkFn(scope, lElement, attrs) { + scope.direction = attrs.direction; + var runScroll = true; + var windowEl = angular.element($window); + windowEl.on("scroll", function() { + if (runScroll) { + lElement.addClass("fade-out"); + $timeout(function() { + lElement.addClass("hide"); + }, 1e3); + runScroll = false; + } + }); + } + }; + } ]); + "use strict"; + AppServices.Directives.directive("bsmodal", [ "$rootScope", function($rootScope) { + return { + restrict: "ECA", + scope: { + title: "@title", + buttonid: "=buttonid", + footertext: "=footertext", + closelabel: "=closelabel" + }, + transclude: true, + templateUrl: "dialogs/modal.html", + replace: true, + link: function linkFn(scope, lElement, attrs, parentCtrl) { + scope.title = attrs.title; + scope.footertext = attrs.footertext; + scope.closelabel = attrs.closelabel; + scope.close = attrs.close; + scope.extrabutton = attrs.extrabutton; + scope.extrabuttonlabel = attrs.extrabuttonlabel; + scope.buttonId = attrs.buttonid; + scope.closeDelegate = function(attr) { + scope.$parent[attr](attrs.id, scope); + }; + scope.extraDelegate = function(attr) { + if (scope.dialogForm.$valid) { + console.log(parentCtrl); + scope.$parent[attr](attrs.id); + } else { + $rootScope.$broadcast("alert", "error", "Please check your form input and resubmit."); + } + }; + } + }; + } ]); + angular.module("appservices").run([ "$templateCache", function($templateCache) { + "use strict"; + $templateCache.put("activities/activities.html", '
\n' + "\n" + '
\n' + '
\n' + '

\n' + ' 📱 Activities\n' + "

\n" + "
\n" + "
\n" + "\n" + "
\n" + '
\n' + '
\n' + '
\n' + " \n" + ' \n' + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ' \n' + " \n" + ' \n' + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
DateUserContentVerbUUID
{{formatDate(activity.created)}}{{activity.actor.displayName}}{{activity.content}}{{activity.verb}}{{activity.uuid}}
\n" + " \n" + "\n"); + $templateCache.put("app-overview/app-overview.html", '
\n' + "\n" + '
\n' + "\n" + ' \n' + '
\n' + '

{{currentApp}}

\n' + "
\n" + '
\n' + "\n" + '
\n' + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + " \n" + " \n" + " \n" + "
PathTitle
{{v.title}}{{v.count}}
\n" + "
\n" + "\n" + "
\n" + "
\n"); + $templateCache.put("app-overview/doc-includes/android.html", "

1. Integrate the SDK into your project

\n" + "\n" + "

You can integrate Apigee features into your app by including the\n" + " SDK in your project.  You can do one of the following:

\n" + "\n" + '\n" + "\n" + '
\n' + '
\n' + ' \n' + "

If you've already got an Android project, you can\n" + " integrate the Apigee SDK into your project as you\n" + " normally would:

\n" + '
\n' + ' Details\n' + "
\n" + '
\n' + "

\n" + " Add\n" + " apigee-android-<version>.jar\n" + " to your class path by doing the following:\n" + "

\n" + "\n" + "

Android 4.0 (or later) projects

\n" + "

\n" + " Copy the jar file into the\n" + " /libs\n" + " folder in your project.\n" + "

\n" + "\n" + "

Android 3.0 (or earlier) projects

\n" + "
    \n" + "
  1. In the Eclipse Package Explorer,\n" + " select your application's project folder.\n" + "
  2. \n" + "
  3. Click the File > Properties menu.\n" + "
  4. \n" + "
  5. In the Java Build Path section, click\n" + " the Libraries tab, click Add\n" + " External JARs.\n" + "
  6. \n" + "
  7. Browse to apigee-android-<version>.jar,\n" + " then click Open.\n" + "
  8. \n" + "
  9. Order the apigee-android-<version>.jar\n" + " at the top of the class path:\n" + "
      \n" + "
    1. In the Eclipse Package Explorer,\n" + " select your application's project folder.\n" + "
    2. \n" + "
    3. Click the File >\n" + " Properties menu.\n" + "
    4. \n" + "
    5. In the properties dialog, in the Java\n" + " Build Path section, click the Order\n" + " and Export tab.\n" + "
    6. \n" + "
    7. \n" + "

      \n" + " IMPORTANT: Select the checkbox for\n" + " apigee-android-<version>.jar\n" + " , then click the Top button.\n" + "

      \n" + "
    8. \n" + "
    \n" + "
  10. \n" + "
\n" + '
\n' + "

Applications using Ant

\n" + "

\n" + " If you are using Ant to build your application, you must also\n" + " copy\n" + " apigee-android-<version>.jar\n" + " to the\n" + " /libs\n" + " folder in your application.\n" + "

\n" + "
\n" + "
\n" + "
\n" + '
\n' + ' \n' + "

If you don't have a project yet, you can begin by using\n" + " the project template included with the SDK. The template includes\n" + " support for SDK features.

\n" + "
    \n" + "
  • Locate the project template in the expanded SDK. It\n" + " should be at the following location:
    <sdk_root>/new-project-template
    \n" + "
  • \n" + "
\n" + "
\n" + "
\n" + "

2. Update permissions in AndroidManifest.xml

\n" + "

\n" + " Add the following Internet permissions to your application's\n" + " AndroidManifest.xml\n" + " file if they have not already been added. Note that with the exception\n" + " of INTERNET, enabling all other permissions are optional.\n" + "

\n" + "
\n" + '<uses-permission android:name="android.permission.INTERNET" />\n' + '<uses-permission android:name="android.permission.READ_PHONE_STATE" />\n' + '<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />\n' + '<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />\n' + '<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />\n' + "
\n" + "

3. Initialize the SDK

\n" + "

\n" + " To initialize the App Services SDK, you must instantiate the\n" + " ApigeeClient\n" + " class. There are multiple ways to handle this step, but we recommend\n" + " that you do the following:\n" + "

\n" + "
    \n" + "
  1. Subclass the Application class, and add an\n" + " instance variable for the ApigeeClient to it, along\n" + " with getter and setter methods.
    \n" + "public class YourApplication extends Application\n" + "{\n" + "        \n" + "        private ApigeeClient apigeeClient;\n" + "        \n" + "        public YourApplication()\n" + "        {\n" + "                this.apigeeClient = null;\n" + "        }\n" + "        \n" + "        public ApigeeClient getApigeeClient()\n" + "        {\n" + "                return this.apigeeClient;\n" + "        }\n" + "        \n" + "        public void setApigeeClient(ApigeeClient apigeeClient)\n" + "        {\n" + "                this.apigeeClient = apigeeClient;\n" + "        }\n" + "}			\n" + "		
    \n" + "
  2. \n" + "
  3. Declare the Application subclass in your AndroidManifest.xml.\n" + " For example:
    \n" + "<application>\n" + '    android:allowBackup="true"\n' + '    android:icon="@drawable/ic_launcher"\n' + '    android:label="@string/app_name"\n' + '    android:name=".YourApplication"\n' + "	…\n" + "</application>			\n" + "		
    \n" + "
  4. \n" + "
  5. Instantiate the ApigeeClient class in the onCreate\n" + " method of your first Activity class:
    \n" + "import com.apigee.sdk.ApigeeClient;\n" + "\n" + "@Override\n" + "protected void onCreate(Bundle savedInstanceState) {\n" + "    super.onCreate(savedInstanceState);		\n" + "	\n" + '	String ORGNAME = "{{currentOrg}}";\n' + '	String APPNAME = "{{currentApp}}";\n' + "	\n" + "	ApigeeClient apigeeClient = new ApigeeClient(ORGNAME,APPNAME,this.getBaseContext());\n" + "\n" + "	// hold onto the ApigeeClient instance in our application object.\n" + "	YourApplication yourApp = (YourApplication) getApplication;\n" + "	yourApp.setApigeeClient(apigeeClient);			\n" + "}\n" + "		
    \n" + "

    \n" + " This will make the instance of\n" + " ApigeeClient\n" + " available to your\n" + " Application\n" + " class.\n" + "

    \n" + "
  6. \n" + "
\n" + "

4. Import additional SDK classes

\n" + "

The following classes will enable you to call common SDK methods:

\n" + "
\n" + "import com.apigee.sdk.data.client.DataClient; //App Services data methods\n" + "import com.apigee.sdk.apm.android.MonitoringClient; //App Monitoring methods\n" + "import com.apigee.sdk.data.client.callbacks.ApiResponseCallback; //API response handling\n" + "import com.apigee.sdk.data.client.response.ApiResponse; //API response object\n" + "
\n" + "\n" + "

5. Verify SDK installation

\n" + "\n" + "

\n" + " Once initialized, App Services will also automatically instantiate the\n" + " MonitoringClient\n" + " class and begin logging usage, crash and error metrics for your app.\n" + "

\n" + "

\n" + ' screenshot of data in admin portal\n' + "

\n" + "

\n" + " To verify that the SDK has been properly initialized, run your app,\n" + " then go to 'Monitoring' > 'App Usage' in the App Services admin portal\n' + " to verify that data is being sent.\n" + "

\n" + '
It may take up to two minutes for data to\n' + " appear in the admin portal after you run your app.
\n" + "\n" + "

Installation complete! Try these next steps

\n" + "
    \n" + "
  • \n" + "

    \n" + " Call additional SDK methods in your code\n" + "

    \n" + "

    \n" + " The\n" + " DataClient\n" + " and\n" + " MonitoringClient\n" + " classes are also automatically instantiated for you, and\n" + " accessible with the following accessors:\n" + "

    \n" + "
      \n" + "
    • DataClient dataClient = apigeeClient.getDataClient();
      \n" + "

      Use this object to access the data methods of the App\n" + " Services SDK, including those for push notifications, data\n" + " store, and geolocation.

    • \n" + "
    • MonitoringClient monitoringClient = apigeeClient.getMonitoringClient();
      \n" + "

      Use this object to access the app configuration and\n" + " monitoring methods of the App Services SDK, including advanced\n" + " logging, and A/B testing.

    • \n" + "
    \n" + "
  • \n" + "
  • \n" + "

    \n" + " Add App Services features to your app\n" + "

    \n" + "

    With App Services you can quickly add valuable features to\n" + " your mobile or web app, including push notifications, a custom\n" + " data store, geolocation and more. Check out these links to get\n" + " started with a few of our most popular features:

    \n" + "
      \n" + "
    • Push notifications:\n' + " Send offers, alerts and other messages directly to user devices\n" + " to dramatically increase engagement. With App Services you can\n" + " send 10 million push notification per month for free!
    • \n" + "
    • App Monitoring: When you initialize the\n" + " App Services SDK, a suite of valuable, customizable\n' + " application monitoring features are automatically enabled that\n" + " deliver the data you need to fine tune performance, analyze\n" + " issues, and improve user experience.\n" + "
        \n" + "
      • App Usage\n' + " Monitoring: Visit the App Services admin\n' + " portal to view usage data for your app, including data on\n" + " device models, platforms and OS versions running your app.
      • \n" + "
      • API\n' + " Performance Monitoring: Network performance is key to a\n" + " solid user experience. In the App Services admin\n' + " portal you can view key metrics, including response time,\n" + " number of requests and raw API request logs.
      • \n" + "
      • Error &\n' + " Crash Monitoring: Get alerted to any errors or crashes,\n" + ' then view them in the App\n' + " Services admin portal, where you can also analyze raw\n" + " error and crash logs.
      • \n" + "
    • \n" + "
    • Geolocation: Target\n' + " users or return result sets based on user location to keep your\n" + " app highly-relevant.
    • \n" + "
    • Data storage:\n' + " Store all your application data on our high-availability\n" + " infrastructure, and never worry about dealing with a database\n" + " ever again.
    • \n" + "
    • User management and\n' + " authentication: Every app needs users. Use App Services to\n" + " easily implement user registration, as well as OAuth\n" + " 2.0-compliant login and authentication.
    • \n" + "
    \n" + "
  • \n" + "
  • \n" + "

    \n" + " Check out the sample apps\n" + "

    \n" + "

    The SDK includes samples that illustrate\n" + " Apigee features. You'll find the samples in the following\n" + " location in your SDK download:

    \n" + "apigee-android-sdk-<version>\n" + "	...\n" + "	/samples\n" + "		
    \n" + '
    \n' + ' Details\n' + "
    \n" + '
    \n' + "

    The samples include the following:

    \n" + ' \n' + " \n" + " \n" + ' \n' + ' \n' + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
    SampleDescription
    booksAn app for storing a list of books that shows\n" + " Apigee database operations such as reading, creating, and\n" + " deleting.
    messageeAn app for sending and receiving messages that\n" + " shows Apigee database operations (reading, creating).
    pushAn app that uses the push feature to send\n" + " notifications to the devices of users who have subscribed\n" + " for them.
    \n" + "
    \n" + "
  • \n" + "
\n"); + $templateCache.put("app-overview/doc-includes/ios.html", "

1. Integrate ApigeeiOSSDK.framework

\n" + "\n" + '\n' + '\n" + '
\n' + '
\n' + "

If you've already got an Xcode iOS project, add it into\n" + " your project as you normally would.

\n" + '
\n' + ' Details\n' + "
\n" + '
\n' + "
    \n" + "
  1. \n" + "

    Locate the SDK framework file so you can add it to your\n" + " project. For example, you'll find the file at the following\n" + " path:

    \n" + "<sdk_root>/bin/ApigeeiOSSDK.framework
    \n" + "
  2. \n" + "
  3. In the Project Navigator, click on\n" + " your project file, and then the Build Phases\n" + " tab. Expand Link Binary With Libraries.\n" + "
  4. \n" + "
  5. Link the Apigee iOS SDK into your project.\n" + "
      \n" + "
    • Drag ApigeeiOSSDK.framework into the Frameworks\n" + " group created by Xcode.
    • \n" + "
    \n" + "

    OR

    \n" + "
      \n" + "
    1. At the bottom of the Link Binary\n" + " With Libraries group, click the +\n" + " button. Then click Add Other.\n" + "
    2. \n" + "
    3. Navigate to the directory that contains\n" + " ApigeeiOSSDK.framework, and choose the\n" + " ApigeeiOSSDK.framework folder.
    4. \n" + "
    \n" + "
  6. \n" + "
\n" + "
\n" + "
\n" + '
\n' + ' \n' + "

If you're starting with a clean slate (you don't have\n" + " a project yet), you can begin by using the project template\n" + " included with the SDK. The template includes support for SDK\n" + " features.

\n" + "
    \n" + "
  1. \n" + "

    Locate the project template in the expanded SDK. It\n" + " should be at the following location:

    \n" + "<sdk_root>/new-project-template
    \n" + "
  2. \n" + "
  3. In the project template directory, open the project\n" + " file: Apigee App Services iOS Template.xcodeproj.
  4. \n" + "
  5. Get acquainted with the template by looking at its readme\n" + " file.
  6. \n" + "
\n" + "
\n" + "
\n" + "

2. Add required iOS frameworks

\n" + "

\n" + " Ensure that the following iOS frameworks are part of your project. To\n" + " add them, under the Link Binary With Libraries group,\n" + " click the + button, type the name of the framework\n" + " you want to add, select the framework found by Xcode, then click Add.\n" + "

\n" + "
    \n" + "
  • QuartzCore.framework
  • \n" + "
  • CoreLocation.framework
  • \n" + "
  • CoreTelephony.framework 
  • \n" + "
  • Security.framework
  • \n" + "
  • SystemConfiguration.framework
  • \n" + "
  • UIKit.framework
  • \n" + "
\n" + "

3. Update 'Other Linker Flags'

\n" + "

\n" + " In the Build Settings panel, add the following under\n" + " Other Linker Flags:\n" + "

\n" + "
\n" + "-ObjC -all_load
\n" + "

\n" + " Confirm that flags are set for both DEBUG and RELEASE.\n" + "

\n" + "

4. Initialize the SDK

\n" + "

\n" + " The ApigeeClient class initializes the App Services SDK. To\n" + " do this you will need your organization name and application name,\n" + " which are available in the Getting Started tab of the App Service admin portal,\n' + " under Mobile SDK Keys.\n" + "

\n" + "
    \n" + "
  1. Import the SDK\n" + "

    Add the following to your source code to import the SDK:

    \n" + "#import <ApigeeiOSSDK/Apigee.h>
    \n" + "
  2. \n" + "
  3. \n" + "

    \n" + " Declare the following properties in\n" + " AppDelegate.h\n" + " :\n" + "

    \n" + "@property (strong, nonatomic) ApigeeClient *apigeeClient; \n" + "@property (strong, nonatomic) ApigeeMonitoringClient *monitoringClient;\n" + "@property (strong, nonatomic) ApigeeDataClient *dataClient;	\n" + "		
    \n" + "
  4. \n" + "
  5. \n" + "

    \n" + " Instantiate the\n" + " ApigeeClient\n" + " class inside the \n" + " didFinishLaunching\n" + " method of\n" + " AppDelegate.m\n" + " :\n" + "

    \n" + "//Replace 'AppDelegate' with the name of your app delegate class to instantiate it\n" + "AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];\n" + "\n" + "//Sepcify your App Services organization and application names\n" + 'NSString *orgName = @"{{currentOrg}}";\n' + 'NSString *appName = @"{{currentApp}}";\n' + "\n" + "//Instantiate ApigeeClient to initialize the SDK\n" + "appDelegate.apigeeClient = [[ApigeeClient alloc]\n" + "                            initWithOrganizationId:orgName\n" + "                            applicationId:appName];\n" + "                            \n" + "//Retrieve instances of ApigeeClient.monitoringClient and ApigeeClient.dataClient\n" + "self.monitoringClient = [appDelegate.apigeeClient monitoringClient]; \n" + "self.dataClient = [appDelegate.apigeeClient dataClient]; \n" + "		
    \n" + "
  6. \n" + "
\n" + "\n" + "

5. Verify SDK installation

\n" + "\n" + "

\n" + " Once initialized, App Services will also automatically instantiate the\n" + " ApigeeMonitoringClient\n" + " class and begin logging usage, crash and error metrics for your app.\n" + "

\n" + "\n" + "

\n" + " To verify that the SDK has been properly initialized, run your app,\n" + " then go to 'Monitoring' > 'App Usage' in the App Services admin portal\n' + " to verify that data is being sent.\n" + "

\n" + "

\n" + ' screenshot of data in admin portal\n' + "

\n" + '
It may take up to two minutes for data to\n' + " appear in the admin portal after you run your app.
\n" + "\n" + "

Installation complete! Try these next steps

\n" + "
    \n" + "
  • \n" + "

    \n" + " Call additional SDK methods in your code\n" + "

    \n" + "

    \n" + " Create an instance of the AppDelegate class, then use\n" + " appDelegate.dataClient\n" + " or\n" + " appDelegate.monitoringClient\n" + " to call SDK methods:\n" + "

    \n" + '
    \n' + ' Details\n' + "
    \n" + '
    \n' + "
      \n" + "
    • appDelegate.dataClient: Used to access the\n" + " data methods of the App Services SDK, including those for push\n" + " notifications, data store, and geolocation.
    • \n" + "
    • appDelegate.monitoringClient: Used to\n" + " access the app configuration and monitoring methods of the App\n" + " Services SDK, including advanced logging, and A/B testing.
    • \n" + "
    \n" + "

    Example

    \n" + "

    For example, you could create a new entity with the\n" + " following:

    \n" + "
    \n" + "AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];\n" + "ApigeeClientResponse *response = [appDelegate.dataClient createEntity:entity];\n" + "			
    \n" + "
    \n" + "\n" + "
  • \n" + "
  • \n" + "

    \n" + " Add App Services features to your app\n" + "

    \n" + "

    With App Services you can quickly add valuable features to\n" + " your mobile or web app, including push notifications, a custom\n" + " data store, geolocation and more. Check out these links to get\n" + " started with a few of our most popular features:

    \n" + "
      \n" + "
    • Push notifications:\n' + " Send offers, alerts and other messages directly to user devices\n" + " to dramatically increase engagement. With App Services you can\n" + " send 10 million push notification per month for free!
    • \n" + "
    • Geolocation: Target\n' + " users or return result sets based on user location to keep your\n" + " app highly-relevant.
    • \n" + "
    • Data storage:\n' + " Store all your application data on our high-availability\n" + " infrastructure, and never worry about dealing with a database\n" + " ever again.
    • \n" + "
    • User management and\n' + " authentication: Every app needs users. Use App Services to\n" + " easily implement user registration, as well as OAuth\n" + " 2.0-compliant login and authentication.
    • \n" + "
    \n" + "
  • \n" + "
  • \n" + "

    \n" + " Check out the sample apps\n" + "

    \n" + "

    \n" + " The SDK includes samples that illustrate Apigee features. To\n" + " look at them, open the .xcodeproj file for each in Xcode. To get a\n" + " sample app running, open its project file, then follow the steps\n" + ' described in the section, Add\n' + " the SDK to an existing project.\n" + "

    \n" + "

    You'll find the samples in the following location in your SDK\n" + " download:

    \n" + "apigee-ios-sdk-<version>\n" + "    ...\n" + "    /samples\n" + "		
    \n" + '
    \n' + ' Details\n' + "
    \n" + '
    \n' + "

    The samples include the following:

    \n" + ' \n' + " \n" + " \n" + ' \n' + ' \n' + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
    SampleDescription
    booksAn app for storing a list of books that shows\n" + " Apigee database operations such as reading, creating, and\n" + " deleting.
    messageeAn app for sending and receiving messages that\n" + " shows Apigee database operations (reading, creating).
    pushAn app that uses the push feature to send\n" + " notifications to the devices of users who have subscribed\n" + " for them.
    \n" + "
    \n" + "

     

    \n" + "
  • \n" + "
\n"); + $templateCache.put("app-overview/doc-includes/javascript.html", "

1. Import the SDK into your HTML

\n" + "\n" + "

\n" + " To enable support for Apigee-related functions in your HTML, you'll\n" + " need to include\n" + " apigee.js\n" + " in your app. To do this, add the following to the\n" + " head\n" + " block of your HTML:\n" + "

\n" + "
\n" + '<script type="text/javascript" src="path/to/js/sdk/apigee.js"></script>\n' + "
\n" + "

2. Instantiate Apigee.Client

\n" + "

Apigee.Client initializes the App Services SDK, and gives you\n" + " access to all of the App Services SDK methods.

\n" + "

You will need to pass a JSON object with the UUID or name for\n" + " your App Services organization and application when you instantiate\n" + " it.

\n" + "
\n" + "//Apigee account credentials, available in the App Services admin portal \n" + "var client_creds = {\n" + "        orgName:'{{currentOrg}}',\n" + "        appName:'{{currentApp}}'\n" + "    }\n" + "\n" + "//Initializes the SDK. Also instantiates Apigee.MonitoringClient\n" + "var dataClient = new Apigee.Client(client_creds);  \n" + "
\n" + "\n" + "

3. Verify SDK installation

\n" + "\n" + "

\n" + " Once initialized, App Services will also automatically instantiate\n" + " Apigee.MonitoringClient\n" + " and begin logging usage, crash and error metrics for your app.\n" + "

\n" + "\n" + "

\n" + " To verify that the SDK has been properly initialized, run your app,\n" + " then go to 'Monitoring' > 'App Usage' in the App Services admin portal\n' + " to verify that data is being sent.\n" + "

\n" + "

\n" + ' screenshot of data in admin portal\n' + "

\n" + '
It may take up to two minutes for data to\n' + " appear in the admin portal after you run your app.
\n" + "\n" + "

Installation complete! Try these next steps

\n" + "
    \n" + "
  • \n" + "

    \n" + " Call additional SDK methods in your code\n" + "

    \n" + "

    \n" + " Use\n" + " dataClient\n" + " or\n" + " dataClient.monitor\n" + " to call SDK methods:\n" + "

    \n" + '
    \n' + ' Details\n' + "
    \n" + '
    \n' + "
      \n" + "
    • dataClient: Used to access the data\n" + " methods of the App Services SDK, including those for push\n" + " notifications, data store, and geolocation.
    • \n" + "
    • dataClient.monitor: Used to access the app\n" + " configuration and monitoring methods of the App Services SDK,\n" + " including advanced logging, and A/B testing.
    • \n" + "
    \n" + "
    \n" + "
  • \n" + "
  • \n" + "

    \n" + " Add App Services features to your app\n" + "

    \n" + "

    With App Services you can quickly add valuable features to\n" + " your mobile or web app, including push notifications, a custom\n" + " data store, geolocation and more. Check out these links to get\n" + " started with a few of our most popular features:

    \n" + "
      \n" + "
    • Push notifications:\n' + " Send offers, alerts and other messages directly to user devices\n" + " to dramatically increase engagement. With App Services you can\n" + " send 10 million push notification per month for free!
    • \n" + "
    • Geolocation: Keep\n' + " your app highly-relevant by targeting users or returning result\n" + " sets based on user location.
    • \n" + "
    • Data storage:\n' + " Store all your application data on our high-availability\n" + " infrastructure, and never worry about dealing with a database\n" + " ever again.
    • \n" + "
    • User management and\n' + " authentication: Every app needs users. Use App Services to\n" + " easily implement registration, login and OAuth 2.0-compliant\n" + " authentication.
    • \n" + "
    \n" + "
  • \n" + "
  • \n" + "

    \n" + " Check out the sample apps\n" + "

    \n" + "

    The SDK includes samples that illustrate\n" + " Apigee features. To look at them, open the .xcodeproj file\n" + " for each in Xcode. You'll find the samples in the following\n" + " location in your SDK download:

    \n" + "apigee-javascript-sdk-master\n" + "    ...\n" + "    /samples		\n" + "		
    \n" + '
    \n' + ' Details\n' + "
    \n" + '
    \n' + "

    The samples include the following:

    \n" + ' \n' + " \n" + " \n" + ' \n' + ' \n' + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
    SampleDescription
    booksSample.htmlAn app for storing a list of books that shows\n" + " Apigee database operations such as reading, creating, and\n" + " deleting.
    messageeAn app for sending and receiving messages that\n" + " shows Apigee database operations (reading, creating).
    monitoringSample.htmlShows basic configuration and initialization of the\n" + " HTML5 app monitoring functionality. Works in browser,\n" + " PhoneGap, Appcelerator, and Trigger.io.
    readmeSample.htmlA simple app for reading data from an Apigee\n" + " database.
    \n" + "
    \n" + "
  • \n" + "
\n"); + $templateCache.put("app-overview/doc-includes/net.html", "\n"); + $templateCache.put("app-overview/doc-includes/node.html", ""); + $templateCache.put("app-overview/doc-includes/ruby.html", ""); + $templateCache.put("data/data.html", '
\n' + "\n" + ' \n' + "
\n" + '
\n' + ' \n' + '
\n' + ' \n' + '

\n' + "
\n" + "
\n" + "
\n" + "
\n" + "\n" + '\n' + "
\n" + '
\n' + ' \n' + '
\n' + ' \n' + '

\n' + "
\n" + '
\n' + ' \n' + " { "name":"value" }\n' + "
\n" + ' Validate JSON\n' + '

\n' + "
\n" + "
\n" + "
\n" + "
\n" + "\n" + '
\n' + ' \n' + "
\n" + "\n" + '
\n' + '
\n' + ' (?)\n' + '
    \n' + " /{{entity.name}}\n' + " \n" + "
\n" + "\n" + "
\n" + "\n" + '
\n' + '
\n' + '
\n' + "
\n" + '
\n' + '
\n' + ' \n' + " \n" + ' \n' + ' CREATE     \n' + ' READ     \n' + ' UPDATE     \n' + ' DELETE (?)\n' + "
\n" + "
\n" + "\n" + '
\n' + " Path \n" + '
\n' + ' \n' + ' (?)\n' + "
\n" + "
\n" + '
\n' + ' \n' + "
\n" + '
\n' + " Query\n" + '
\n' + ' (?)\n' + '
\n' + ' \n' + ' \n' + " \n" + ' \n" + "
\n" + "
\n" + "
\n" + "\n" + "\n" + '
\n" + ' \n' + '
\n' + '
\n' + ' \n' + "
\n" + "
\n" + "
\n" + "\n" + '
\n' + ' \n' + '
\n' + ' \n" + '
Validate JSON (?)\n' + "
\n" + "
\n" + '
\n' + '
\n' + ' (?)\n' + "
\n" + "
\n" + "
\n" + '
\n' + "
\n" + "
\n" + "
\n" + "
\n" + " \n" + "\n" + " \n" + "\n" + " \n" + " \n" + "\n" + "\n" + "\n"); + $templateCache.put("data/display-generic.html", '\n' + " \n" + "
\n" + '
\n' + "
\n" + "
\n" + "\n" + ' (?)\n' + ' \n" + "\n" + '\n' + " \n" + ' \n' + ' \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ' \n' + ' \n' + ' \n" + " \n" + " \n" + ' \n" + " \n" + ' \n' + ' \n" + " \n" + "\n" + ' \n' + ' \n' + " \n" + " \n" + "
NameUUID
\n' + " {{entity._data.name}}{{entity._data.uuid}}{{entitySelected[$index]\n' + " ? 'Hide' : 'View'}} Details
\n' + "\n" + "\n" + '

Entity Detail

\n' + "\n" + "\n" + '
    \n' + '
  • {{k}} : \n' + ' \n' + '
      \n' + '
    • {{k2}}\n' + ' : \n' + '
        \n' + '
      • {{k3}} :{{v3}}
      • \n' + '
      {{v2}}\n' + "
      \n" + "
    • \n" + '
    {{v}}\n' + " \n" + "
  • \n" + "
\n" + "\n" + '
\n' + '

\n' + ' Edit Entity (?)\n' + "

\n" + '
\n' + ' \n' + '
Validate JSON\n' + ' \n' + "
\n" + "
\n" + "
No data found
\n" + '
\n' + ' \n' + ' \n' + "
\n" + "\n"); + $templateCache.put("data/display-groups.html", ""); + $templateCache.put("data/display-roles.html", "roles---------------------------------\n" + "\n"); + $templateCache.put("data/display-users.html", '\n' + "\n" + " \n" + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + ' \n' + ' \n' + ' \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n" + " \n" + " \n" + "
 UsernameDisplay NameUUID 
10#"><img src=x\n' + " onerror=prompt(1);>bf9a95da-d508-11e2-bf44-236d2eee13a7Details
\n"); + $templateCache.put("data/entity.html", '
\n' + "\n" + "

Entity Detail

\n" + '
\n' + ' << Back to collection\n' + "
\n" + "
\n" + '
\n' + " Path \n" + '
{{entityType}}/{{entityUUID}}
\n' + "
\n" + "\n" + '
\n' + ' \n" + '
\n' + ' \n' + '
Validate\n' + " JSON\n" + "
\n" + "
\n" + '
\n' + '
\n' + ' \n' + ' \n' + "
\n" + "
\n" + "\n" + "
\n" + "\n"); + $templateCache.put("dialogs/modal.html", '\n"); + $templateCache.put("global/insecure-banner.html", '
\n' + "\n" + '
\n' + '
\n' + ' Warning: This application has\n' + ' "sandbox" permissions and is not production ready. Please\n' + " go to our security documentation to find out more.\n" + "
\n" + "
\n" + "
\n"); + $templateCache.put("global/page-title.html", '
\n' + "\n" + '
\n' + '
\n' + '

\n' + ' {{icon}}{{title}}\n' + ' (need help?)\n' + "

\n" + "
\n" + "
\n" + ' \n' + "

Do you want to contact support? Support will get in touch with\n" + " you as soon as possible.

\n" + "
\n" + "
\n" + "\n"); + $templateCache.put("groups/groups-activities.html", '
\n' + "\n" + "
\n" + "
\n" + ' \n' + " \n" + ' \n' + " \n" + " \n" + " \n" + " \n" + " \n" + ' \n' + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
DateContentVerbUUID
{{activity.createdDate}}{{activity.content}}{{activity.verb}}{{activity.uuid}}
\n" + "
\n" + "\n" + "\n" + "
\n"); + $templateCache.put("groups/groups-details.html", '
\n' + "\n" + "
\n" + '
\n" + '
\n' + '

Group Information

\n' + ' \n' + ' (?)
Group Path \n' + ' (?)
\n' + "
\n" + '
\n' + "\n" + '
\n' + ' \n' + "
\n" + "\n" + '
\n' + "

\n" + ' JSON Group Object (?)\n' + "

\n" + '
{{json}}
\n' + "
\n" + "
\n" + "
\n" + "\n" + "\n" + "
\n"); + $templateCache.put("groups/groups-members.html", '
\n' + "\n" + ' \n' + "

Are you sure you want to remove the users from the seleted\n" + " group(s)?

\n" + "
\n" + "\n" + ' \n' + '
\n' + ' {{$parent.user\n' + " != '' ? $parent.user.username : 'Select a user...'}} \n' + " \n" + ' \n" + "
\n" + "
\n" + "\n" + "\n" + '
\n' + ' (?)\n' + ' \n" + ' \n" + "
\n" + ' \n' + ' \n' + ' \n" + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n" + ' \n' + " \n" + " \n" + " \n" + "
UsernameDisplay Name
\n' + " {{user.get('username')}}{{user.get('name')}}
\n" + '
\n' + ' \n' + ' \n' + "
\n" + "
\n"); + $templateCache.put("groups/groups-roles.html", '
\n' + "\n" + ' \n' + '
\n' + ' {{$parent.name\n' + " != '' ? $parent.name : 'Role name...'}} \n" + " \n" + ' \n" + "
\n" + "
\n" + "\n" + ' \n' + "

Are you sure you want to remove the group from the role(s)?

\n" + "
\n" + "\n" + "\n" + '
\n' + ' (?)\n' + ' \n" + ' \n" + "
\n" + "

\n" + ' Roles (?)\n' + "

\n" + ' \n' + " \n" + ' \n' + ' \n" + " \n" + " \n" + " \n" + ' \n' + ' \n" + " \n" + " \n" + " \n" + " \n" + "
Role NameRole title
\n' + " {{role._data.name}}{{role._data.title}}
\n" + '
\n' + ' \n' + ' \n' + "
\n" + "\n" + "\n" + ' \n' + "

Are you sure you want to delete the permission(s)?

\n" + "
\n" + "\n" + "\n" + ' \n' + "

\n" + ' Path: (?)\n' + "

\n" + '
\n' + ' \n' + ' GET (?)\n' + "
\n" + '
\n' + ' \n' + " POST\n" + "
\n" + '
\n' + ' \n' + " PUT\n" + "
\n" + '
\n' + ' \n' + " DELETE\n" + "
\n" + "
\n" + "\n" + "\n" + '
\n' + ' (?)\n' + ' \n" + ' \n" + "
\n" + "

\n" + ' Permissions (?)\n' + "

\n" + ' \n' + " \n" + ' \n' + ' \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ' \n' + ' \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
PathGETPOSTPUTDELETE
\n' + " {{permission.path}}{{permission.operations.get}}{{permission.operations.post}}{{permission.operations.put}}{{permission.operations.delete}}
\n" + "\n" + "
\n"); + $templateCache.put("groups/groups-tabs.html", '
\n' + "\n" + '
\n' + "\n" + '
\n' + '
\n' + '

\n' + ' 👥 Groups\n' + "

\n" + "
\n" + "
\n" + "\n" + "
\n" + "\n" + '
\n' + ' \n" + "
\n" + "\n" + '
\n' + '
\n' + '
\n' + " Group Path: {{selectedGroup.get('path')}}\n" + "
\n" + '
\n' + " Group Title: {{selectedGroup.get('title')}}\n" + "
\n" + "
\n" + "
\n" + "
\n" + "
\n" + "
\n"); + $templateCache.put("groups/groups.html", '
\n' + "\n" + '
\n' + ' \n' + "\n" + "
\n" + ' \n' + "
\n" + '
\n' + ' \n' + '
\n' + ' \n' + ' (?)\n' + "
\n" + "
\n" + '
\n' + ' \n' + '
\n' + ' (?)\n' + "
\n" + "
\n" + "
\n" + "
\n" + "\n" + ' \n' + "

Are you sure you want to delete the group(s)?

\n" + "
\n" + "\n" + "\n" + '
\n' + '
\n' + '
\n' + ' \n" + ' \n' + " \n" + ' \n" + ' \n" + ' (?)\n' + "
\n" + ' \n" + "\n" + "\n" + '
\n' + ' \n' + ' \n' + "
\n" + "
\n" + "\n" + '
\n' + ' \n" + '
  • \n' + ' 👥Users (?)\n' + "
  • \n" + '
  • \n' + ' Activities (?)\n' + "
  • \n" + '
  • \n' + ' 🌎Roles & Permissions (?)\n' + "
  • \n" + " \n" + " \n" + ' \n' + " \n" + "\n"); + $templateCache.put("login/forgot-password.html", '").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});return a.fn.bgiframe&&c.bgiframe(),this.instances.push(c),c},destroy:function(b){var c=a.inArray(b,this.instances);-1!=c&&this.oldInstances.push(this.instances.splice(c,1)[0]),0===this.instances.length&&a([document,window]).unbind(".dialog-overlay"),b.remove();var d=0;a.each(this.instances,function(){d=Math.max(d,this.css("z-index"))}),this.maxZ=d},height:function(){var b,c;return a.browser.msie&&a.browser.version<7?(b=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),c=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),c>b?a(window).height()+"px":b+"px"):a(document).height()+"px"},width:function(){var b,c;return a.browser.msie?(b=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),c=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth),c>b?a(window).width()+"px":b+"px"):a(document).width()+"px"},resize:function(){var b=a([]);a.each(a.ui.dialog.overlay.instances,function(){b=b.add(this)}),b.css({width:0,height:0}).css({width:a.ui.dialog.overlay.width(),height:a.ui.dialog.overlay.height()})}}),a.extend(a.ui.dialog.overlay.prototype,{destroy:function(){a.ui.dialog.overlay.destroy(this.$el)}})}(jQuery),function(a){a.ui=a.ui||{};var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var l,m,n,h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0];return 9===i.nodeType?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");1===a.length&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),1===j.length&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,1===k.length&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,"right"===b.at[0]?n.left+=l:b.at[0]===e&&(n.left+=l/2),"bottom"===b.at[1]?n.top+=m:b.at[1]===e&&(n.top+=m/2),n.left+=k[0],n.top+=k[1],this.each(function(){var r,c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n);"right"===b.my[0]?q.left-=d:b.my[0]===e&&(q.left-=d/2),"bottom"===b.my[1]?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(); +b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]!==e){var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g="left"===c.my[0]?-c.elemWidth:"right"===c.my[0]?c.elemWidth:0,h="left"===c.at[0]?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0}},top:function(b,c){if(c.at[1]!==e){var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g="top"===c.my[1]?-c.elemHeight:"bottom"===c.my[1]?c.elemHeight:0,h="top"===c.at[1]?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];return c&&c.ownerDocument?b?this.each(function(){a.offset.setOffset(this,b)}):h.call(this):null}),function(){var d,e,g,h,i,b=document.getElementsByTagName("body")[0],c=document.createElement("div");d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&22>i}()}(jQuery),function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("
    ").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){return a===b?this._value():(this._setOption("value",a),this)},_setOption:function(b,c){"value"===b&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;return"number"!=typeof a&&(a=0),Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.18"})}(jQuery),function(a){var c=5;a.widget("ui.slider",a.ui.mouse,{widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var b=this,d=this.options,e=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),f="",g=d.values&&d.values.length||1,h=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all"+(d.disabled?" ui-slider-disabled ui-disabled":"")),this.range=a([]),d.range&&(d.range===!0&&(d.values||(d.values=[this._valueMin(),this._valueMin()]),d.values.length&&2!==d.values.length&&(d.values=[d.values[0],d.values[0]])),this.range=a("
    ").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+("min"===d.range||"max"===d.range?" ui-slider-range-"+d.range:"")));for(var i=e.length;g>i;i+=1)h.push(f);this.handles=e.add(a(h.join("")).appendTo(b.element)),this.handle=this.handles.eq(0),this.handles.add(this.range).filter("a").click(function(a){a.preventDefault()}).hover(function(){d.disabled||a(this).addClass("ui-state-hover")},function(){a(this).removeClass("ui-state-hover")}).focus(function(){d.disabled?a(this).blur():(a(".ui-slider .ui-state-focus").removeClass("ui-state-focus"),a(this).addClass("ui-state-focus"))}).blur(function(){a(this).removeClass("ui-state-focus")}),this.handles.each(function(b){a(this).data("index.ui-slider-handle",b)}),this.handles.keydown(function(d){var f,g,h,i,e=a(this).data("index.ui-slider-handle");if(!b.options.disabled){switch(d.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.PAGE_UP:case a.ui.keyCode.PAGE_DOWN:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(d.preventDefault(),!b._keySliding&&(b._keySliding=!0,a(this).addClass("ui-state-active"),f=b._start(d,e),f===!1))return}switch(i=b.options.step,g=h=b.options.values&&b.options.values.length?b.values(e):b.value(),d.keyCode){case a.ui.keyCode.HOME:h=b._valueMin();break;case a.ui.keyCode.END:h=b._valueMax();break;case a.ui.keyCode.PAGE_UP:h=b._trimAlignValue(g+(b._valueMax()-b._valueMin())/c);break;case a.ui.keyCode.PAGE_DOWN:h=b._trimAlignValue(g-(b._valueMax()-b._valueMin())/c);break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(g===b._valueMax())return;h=b._trimAlignValue(g+i);break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(g===b._valueMin())return;h=b._trimAlignValue(g-i)}b._slide(d,e,h)}}).keyup(function(c){var d=a(this).data("index.ui-slider-handle");b._keySliding&&(b._keySliding=!1,b._stop(c,d),b._change(c,d),a(this).removeClass("ui-state-active"))}),this._refreshValue(),this._animateOff=!1},destroy:function(){return this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider"),this._mouseDestroy(),this},_mouseCapture:function(b){var d,e,f,g,h,i,j,k,l,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),d={x:b.pageX,y:b.pageY},e=this._normValueFromMouse(d),f=this._valueMax()-this._valueMin()+1,h=this,this.handles.each(function(b){var c=Math.abs(e-h.values(b));f>c&&(f=c,g=a(this),i=b)}),c.range===!0&&this.values(1)===c.min&&(i+=1,g=a(this.handles[i])),j=this._start(b,i),j===!1?!1:(this._mouseSliding=!0,h._handleIndex=i,g.addClass("ui-state-active").focus(),k=g.offset(),l=!a(b.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:b.pageX-k.left-g.width()/2,top:b.pageY-k.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(b,i,e),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(a){var b={x:a.pageX,y:a.pageY},c=this._normValueFromMouse(b);return this._slide(a,this._handleIndex,c),!1},_mouseStop:function(a){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(a,this._handleIndex),this._change(a,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(a){var b,c,d,e,f;return"horizontal"===this.orientation?(b=this.elementSize.width,c=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(b=this.elementSize.height,c=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),d=c/b,d>1&&(d=1),0>d&&(d=0),"vertical"===this.orientation&&(d=1-d),e=this._valueMax()-this._valueMin(),f=this._valueMin()+d*e,this._trimAlignValue(f)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};return this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("start",a,c)},_slide:function(a,b,c){var d,e,f;this.options.values&&this.options.values.length?(d=this.values(b?0:1),2===this.options.values.length&&this.options.range===!0&&(0===b&&c>d||1===b&&d>c)&&(c=d),c!==this.values(b)&&(e=this.values(),e[b]=c,f=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e}),d=this.values(b?0:1),f!==!1&&this.values(b,c,!0))):c!==this.value()&&(f=this._trigger("slide",a,{handle:this.handles[b],value:c}),f!==!1&&this.value(c))},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("change",a,c)}},value:function(a){return arguments.length?(this.options.value=this._trimAlignValue(a),this._refreshValue(),this._change(null,0),void 0):this._value()},values:function(b,c){var d,e,f;if(arguments.length>1)this.options.values[b]=this._trimAlignValue(c),this._refreshValue(),this._change(null,b);else{if(!arguments.length)return this._values();if(!a.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(b):this.value();for(d=this.options.values,e=arguments[0],f=0;fd;d+=1)this._change(null,d);this._animateOff=!1}},_value:function(){var a=this.options.value;return a=this._trimAlignValue(a)},_values:function(a){var b,c,d;if(arguments.length)return b=this.options.values[a],b=this._trimAlignValue(b);for(c=this.options.values.slice(),d=0;d=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b,d=a-c;return 2*Math.abs(c)>=b&&(d+=c>0?b:-b),parseFloat(d.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var f,h,i,j,k,b=this.options.range,c=this.options,d=this,e=this._animateOff?!1:c.animate,g={};this.options.values&&this.options.values.length?this.handles.each(function(b){f=(d.values(b)-d._valueMin())/(d._valueMax()-d._valueMin())*100,g["horizontal"===d.orientation?"left":"bottom"]=f+"%",a(this).stop(1,1)[e?"animate":"css"](g,c.animate),d.options.range===!0&&("horizontal"===d.orientation?(0===b&&d.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},c.animate),1===b&&d.range[e?"animate":"css"]({width:f-h+"%"},{queue:!1,duration:c.animate})):(0===b&&d.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},c.animate),1===b&&d.range[e?"animate":"css"]({height:f-h+"%"},{queue:!1,duration:c.animate}))),h=f}):(i=this.value(),j=this._valueMin(),k=this._valueMax(),f=k!==j?(i-j)/(k-j)*100:0,g["horizontal"===d.orientation?"left":"bottom"]=f+"%",this.handle.stop(1,1)[e?"animate":"css"](g,c.animate),"min"===b&&"horizontal"===this.orientation&&this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},c.animate),"max"===b&&"horizontal"===this.orientation&&this.range[e?"animate":"css"]({width:100-f+"%"},{queue:!1,duration:c.animate}),"min"===b&&"vertical"===this.orientation&&this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},c.animate),"max"===b&&"vertical"===this.orientation&&this.range[e?"animate":"css"]({height:100-f+"%"},{queue:!1,duration:c.animate}))}}),a.extend(a.ui.slider,{version:"1.8.18"})}(jQuery),function(a,b){function f(){return++d}function e(){return++c}var c=0,d=0;a.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:!1,cookie:null,collapsible:!1,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
    ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:"
  • #{label}
  • "},_create:function(){this._tabify(!0)},_setOption:function(a,b){if("selected"==a){if(this.options.collapsible&&b==this.options.selected)return;this.select(b)}else this.options[a]=b,this._tabify()},_tabId:function(a){return a.title&&a.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+e()},_sanitizeSelector:function(a){return a.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+f());return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(a,b){return{tab:a,panel:b,index:this.anchors.index(a)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function m(b,c){b.css("display",""),!a.support.opacity&&c.opacity&&b[0].style.removeAttribute("filter")}var d=this,e=this.options,f=/^#.+/;this.list=this.element.find("ol,ul").eq(0),this.lis=a(" > li:has(a[href])",this.list),this.anchors=this.lis.map(function(){return a("a",this)[0]}),this.panels=a([]),this.anchors.each(function(b,c){var i,g=a(c).attr("href"),h=g.split("#")[0];if(h&&(h===location.toString().split("#")[0]||(i=a("base")[0])&&h===i.href)&&(g=c.hash,c.href=g),f.test(g))d.panels=d.panels.add(d.element.find(d._sanitizeSelector(g)));else if(g&&"#"!==g){a.data(c,"href.tabs",g),a.data(c,"load.tabs",g.replace(/#.*$/,""));var j=d._tabId(c);c.href="#"+j;var k=d.element.find("#"+j);k.length||(k=a(e.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(d.panels[b-1]||d.list),k.data("destroy.tabs",!0)),d.panels=d.panels.add(k)}else e.disabled.push(b)}),c?(this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"),this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.lis.addClass("ui-state-default ui-corner-top"),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom"),e.selected===b?(location.hash&&this.anchors.each(function(a,b){return b.hash==location.hash?(e.selected=a,!1):void 0}),"number"!=typeof e.selected&&e.cookie&&(e.selected=parseInt(d._cookie(),10)),"number"!=typeof e.selected&&this.lis.filter(".ui-tabs-selected").length&&(e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))),e.selected=e.selected||(this.lis.length?0:-1)):null===e.selected&&(e.selected=-1),e.selected=e.selected>=0&&this.anchors[e.selected]||e.selected<0?e.selected:0,e.disabled=a.unique(e.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(a){return d.lis.index(a)}))).sort(),-1!=a.inArray(e.selected,e.disabled)&&e.disabled.splice(a.inArray(e.selected,e.disabled),1),this.panels.addClass("ui-tabs-hide"),this.lis.removeClass("ui-tabs-selected ui-state-active"),e.selected>=0&&this.anchors.length&&(d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash)).removeClass("ui-tabs-hide"),this.lis.eq(e.selected).addClass("ui-tabs-selected ui-state-active"),d.element.queue("tabs",function(){d._trigger("show",null,d._ui(d.anchors[e.selected],d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash))[0]))}),this.load(e.selected)),a(window).bind("unload",function(){d.lis.add(d.anchors).unbind(".tabs"),d.lis=d.anchors=d.panels=null})):e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")),this.element[e.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible"),e.cookie&&this._cookie(e.selected,e.cookie);for(var h,g=0;h=this.lis[g];g++)a(h)[-1==a.inArray(g,e.disabled)||a(h).hasClass("ui-tabs-selected")?"removeClass":"addClass"]("ui-state-disabled");if(e.cache===!1&&this.anchors.removeData("cache.tabs"),this.lis.add(this.anchors).unbind(".tabs"),"mouseover"!==e.event){var i=function(a,b){b.is(":not(.ui-state-disabled)")&&b.addClass("ui-state-"+a)},j=function(a,b){b.removeClass("ui-state-"+a)};this.lis.bind("mouseover.tabs",function(){i("hover",a(this))}),this.lis.bind("mouseout.tabs",function(){j("hover",a(this))}),this.anchors.bind("focus.tabs",function(){i("focus",a(this).closest("li"))}),this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var k,l;e.fx&&(a.isArray(e.fx)?(k=e.fx[0],l=e.fx[1]):k=l=e.fx);var n=l?function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.hide().removeClass("ui-tabs-hide").animate(l,l.duration||"normal",function(){m(c,l),d._trigger("show",null,d._ui(b,c[0]))})}:function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.removeClass("ui-tabs-hide"),d._trigger("show",null,d._ui(b,c[0]))},o=k?function(a,b){b.animate(k,k.duration||"normal",function(){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),m(b,k),d.element.dequeue("tabs")})}:function(a,b){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),d.element.dequeue("tabs")};this.anchors.bind(e.event+".tabs",function(){var b=this,c=a(b).closest("li"),f=d.panels.filter(":not(.ui-tabs-hide)"),g=d.element.find(d._sanitizeSelector(b.hash));if(c.hasClass("ui-tabs-selected")&&!e.collapsible||c.hasClass("ui-state-disabled")||c.hasClass("ui-state-processing")||d.panels.filter(":animated").length||d._trigger("select",null,d._ui(this,g[0]))===!1)return this.blur(),!1;if(e.selected=d.anchors.index(this),d.abort(),e.collapsible){if(c.hasClass("ui-tabs-selected"))return e.selected=-1,e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){o(b,f)}).dequeue("tabs"),this.blur(),!1;if(!f.length)return e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this)),this.blur(),!1}if(e.cookie&&d._cookie(e.selected,e.cookie),!g.length)throw"jQuery UI Tabs: Mismatching fragment identifier.";f.length&&d.element.queue("tabs",function(){o(b,f)}),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this)),a.browser.msie&&this.blur()}),this.anchors.bind("click.tabs",function(){return!1})},_getIndex:function(a){return"string"==typeof a&&(a=this.anchors.index(this.anchors.filter("[href$="+a+"]"))),a},destroy:function(){var b=this.options;return this.abort(),this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs"),this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.anchors.each(function(){var b=a.data(this,"href.tabs");b&&(this.href=b);var c=a(this).unbind(".tabs");a.each(["href","load","cache"],function(a,b){c.removeData(b+".tabs")})}),this.lis.unbind(".tabs").add(this.panels).each(function(){a.data(this,"destroy.tabs")?a(this).remove():a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}),b.cookie&&this._cookie(null,b.cookie),this},add:function(c,d,e){e===b&&(e=this.anchors.length);var f=this,g=this.options,h=a(g.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,d)),i=c.indexOf("#")?this._tabId(a("a",h)[0]):c.replace("#","");h.addClass("ui-state-default ui-corner-top").data("destroy.tabs",!0);var j=f.element.find("#"+i);return j.length||(j=a(g.panelTemplate).attr("id",i).data("destroy.tabs",!0)),j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"),e>=this.lis.length?(h.appendTo(this.list),j.appendTo(this.list[0].parentNode)):(h.insertBefore(this.lis[e]),j.insertBefore(this.panels[e])),g.disabled=a.map(g.disabled,function(a){return a>=e?++a:a}),this._tabify(),1==this.anchors.length&&(g.selected=0,h.addClass("ui-tabs-selected ui-state-active"),j.removeClass("ui-tabs-hide"),this.element.queue("tabs",function(){f._trigger("show",null,f._ui(f.anchors[0],f.panels[0]))}),this.load(0)),this._trigger("add",null,this._ui(this.anchors[e],this.panels[e])),this},remove:function(b){b=this._getIndex(b);var c=this.options,d=this.lis.eq(b).remove(),e=this.panels.eq(b).remove();return d.hasClass("ui-tabs-selected")&&this.anchors.length>1&&this.select(b+(b+1=b?--a:a}),this._tabify(),this._trigger("remove",null,this._ui(d.find("a")[0],e[0])),this},enable:function(b){b=this._getIndex(b);var c=this.options;return-1!=a.inArray(b,c.disabled)?(this.lis.eq(b).removeClass("ui-state-disabled"),c.disabled=a.grep(c.disabled,function(a){return a!=b}),this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b])),this):void 0},disable:function(a){a=this._getIndex(a);var c=this.options;return a!=c.selected&&(this.lis.eq(a).addClass("ui-state-disabled"),c.disabled.push(a),c.disabled.sort(),this._trigger("disable",null,this._ui(this.anchors[a],this.panels[a]))),this},select:function(a){if(a=this._getIndex(a),-1==a){if(!this.options.collapsible||-1==this.options.selected)return this;a=this.options.selected}return this.anchors.eq(a).trigger(this.options.event+".tabs"),this},load:function(b){b=this._getIndex(b);var c=this,d=this.options,e=this.anchors.eq(b)[0],f=a.data(e,"load.tabs");if(this.abort(),f&&(0===this.element.queue("tabs").length||!a.data(e,"cache.tabs"))){if(this.lis.eq(b).addClass("ui-state-processing"),d.spinner){var g=a("span",e);g.data("label.tabs",g.html()).html(d.spinner)}return this.xhr=a.ajax(a.extend({},d.ajaxOptions,{url:f,success:function(f,g){c.element.find(c._sanitizeSelector(e.hash)).html(f),c._cleanup(),d.cache&&a.data(e,"cache.tabs",!0),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.success(f,g)}catch(h){}},error:function(a,f){c._cleanup(),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.error(a,f,b,e)}catch(g){}}})),c.element.dequeue("tabs"),this}this.element.dequeue("tabs")},abort:function(){return this.element.queue([]),this.panels.stop(!1,!0),this.element.queue("tabs",this.element.queue("tabs").splice(-2,2)),this.xhr&&(this.xhr.abort(),delete this.xhr),this._cleanup(),this},url:function(a,b){return this.anchors.eq(a).removeData("cache.tabs").data("load.tabs",b),this},length:function(){return this.anchors.length}}),a.extend(a.ui.tabs,{version:"1.8.18"}),a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(a,b){var c=this,d=this.options,e=c._rotate||(c._rotate=function(b){clearTimeout(c.rotation),c.rotation=setTimeout(function(){var a=d.selected;c.select(++aa?-1:a>b?1:0;throw new TypeError(a+" - "+b)},a.equals=function(a,b){return 0===a.compareTo(b)},a.getDayNumberFromName=function(a){for(var b=c.dayNames,d=c.abbreviatedDayNames,e=c.shortestDayNames,f=a.toLowerCase(),g=0;g=a.getTime()&&this.getTime()<=b.getTime()},b.isAfter=function(a){return 1===this.compareTo(a||new Date)},b.isBefore=function(a){return-1===this.compareTo(a||new Date)},b.isToday=function(){return this.isSameDay(new Date)},b.isSameDay=function(a){return this.clone().clearTime().equals(a.clone().clearTime())},b.addMilliseconds=function(a){return this.setMilliseconds(this.getMilliseconds()+a),this},b.addSeconds=function(a){return this.addMilliseconds(1e3*a)},b.addMinutes=function(a){return this.addMilliseconds(6e4*a)},b.addHours=function(a){return this.addMilliseconds(36e5*a)},b.addDays=function(a){return this.setDate(this.getDate()+a),this},b.addWeeks=function(a){return this.addDays(7*a)},b.addMonths=function(b){var c=this.getDate();return this.setDate(1),this.setMonth(this.getMonth()+b),this.setDate(Math.min(c,a.getDaysInMonth(this.getFullYear(),this.getMonth()))),this},b.addYears=function(a){return this.addMonths(12*a)},b.add=function(a){if("number"==typeof a)return this._orient=a,this;var b=a;return b.milliseconds&&this.addMilliseconds(b.milliseconds),b.seconds&&this.addSeconds(b.seconds),b.minutes&&this.addMinutes(b.minutes),b.hours&&this.addHours(b.hours),b.weeks&&this.addWeeks(b.weeks),b.months&&this.addMonths(b.months),b.years&&this.addYears(b.years),b.days&&this.addDays(b.days),this};var e,f,g;b.getWeek=function(){var a,b,c,d,h,i,j,k,l,m;return e=e?e:this.getFullYear(),f=f?f:this.getMonth()+1,g=g?g:this.getDate(),2>=f?(a=e-1,b=(a/4|0)-(a/100|0)+(a/400|0),c=((a-1)/4|0)-((a-1)/100|0)+((a-1)/400|0),l=b-c,h=0,i=g-1+31*(f-1)):(a=e,b=(a/4|0)-(a/100|0)+(a/400|0),c=((a-1)/4|0)-((a-1)/100|0)+((a-1)/400|0),l=b-c,h=l+1,i=g+(153*(f-3)+2)/5+58+l),j=(a+b)%7,d=(i+j-h)%7,k=i+3-d|0,m=0>k?53-((j-l)/5|0):k>364+l?1:(k/7|0)+1,e=f=g=null,m},b.getISOWeek=function(){return e=this.getUTCFullYear(),f=this.getUTCMonth()+1,g=this.getUTCDate(),d(this.getWeek())},b.setWeek=function(a){return this.moveToDayOfWeek(1).addWeeks(a-this.getWeek())},a._validate=function(a,b,c,d){if("undefined"==typeof a)return!1;if("number"!=typeof a)throw new TypeError(a+" is not a Number.");if(b>a||a>c)throw new RangeError(a+" is not a valid value for "+d+".");return!0},a.validateMillisecond=function(b){return a._validate(b,0,999,"millisecond")},a.validateSecond=function(b){return a._validate(b,0,59,"second")},a.validateMinute=function(b){return a._validate(b,0,59,"minute")},a.validateHour=function(b){return a._validate(b,0,23,"hour")},a.validateDay=function(b,c,d){return a._validate(b,1,a.getDaysInMonth(c,d),"day")},a.validateMonth=function(b){return a._validate(b,0,11,"month")},a.validateYear=function(b){return a._validate(b,0,9999,"year")},b.set=function(b){return a.validateMillisecond(b.millisecond)&&this.addMilliseconds(b.millisecond-this.getMilliseconds()),a.validateSecond(b.second)&&this.addSeconds(b.second-this.getSeconds()),a.validateMinute(b.minute)&&this.addMinutes(b.minute-this.getMinutes()),a.validateHour(b.hour)&&this.addHours(b.hour-this.getHours()),a.validateMonth(b.month)&&this.addMonths(b.month-this.getMonth()),a.validateYear(b.year)&&this.addYears(b.year-this.getFullYear()),a.validateDay(b.day,this.getFullYear(),this.getMonth())&&this.addDays(b.day-this.getDate()),b.timezone&&this.setTimezone(b.timezone),b.timezoneOffset&&this.setTimezoneOffset(b.timezoneOffset),b.week&&a._validate(b.week,0,53,"week")&&this.setWeek(b.week),this},b.moveToFirstDayOfMonth=function(){return this.set({day:1})},b.moveToLastDayOfMonth=function(){return this.set({day:a.getDaysInMonth(this.getFullYear(),this.getMonth())})},b.moveToNthOccurrence=function(a,b){var c=0;if(b>0)c=b-1;else if(-1===b)return this.moveToLastDayOfMonth(),this.getDay()!==a&&this.moveToDayOfWeek(a,-1),this;return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(a,1).addWeeks(c)},b.moveToDayOfWeek=function(a,b){var c=(a-this.getDay()+7*(b||1))%7; +return this.addDays(0===c?c+=7*(b||1):c)},b.moveToMonth=function(a,b){var c=(a-this.getMonth()+12*(b||1))%12;return this.addMonths(0===c?c+=12*(b||1):c)},b.getOrdinalNumber=function(){return Math.ceil((this.clone().clearTime()-new Date(this.getFullYear(),0,1))/864e5)+1},b.getTimezone=function(){return a.getTimezoneAbbreviation(this.getUTCOffset())},b.setTimezoneOffset=function(a){var b=this.getTimezoneOffset(),c=-6*Number(a)/10;return this.addMinutes(c-b)},b.setTimezone=function(b){return this.setTimezoneOffset(a.getTimezoneOffset(b))},b.hasDaylightSavingTime=function(){return Date.today().set({month:0,day:1}).getTimezoneOffset()!==Date.today().set({month:6,day:1}).getTimezoneOffset()},b.isDaylightSavingTime=function(){return this.hasDaylightSavingTime()&&(new Date).getTimezoneOffset()===Date.today().set({month:6,day:1}).getTimezoneOffset()},b.getUTCOffset=function(){var b,a=-10*this.getTimezoneOffset()/6;return 0>a?(b=(a-1e4).toString(),b.charAt(0)+b.substr(2)):(b=(a+1e4).toString(),"+"+b.substr(1))},b.getElapsed=function(a){return(a||new Date)-this},b.toISOString||(b.toISOString=function(){function a(a){return 10>a?"0"+a:a}return'"'+this.getUTCFullYear()+"-"+a(this.getUTCMonth()+1)+"-"+a(this.getUTCDate())+"T"+a(this.getUTCHours())+":"+a(this.getUTCMinutes())+":"+a(this.getUTCSeconds())+'Z"'}),b._toString=b.toString,b.toString=function(a){var b=this;if(a&&1==a.length){var e=c.formatPatterns;switch(b.t=b.toString,a){case"d":return b.t(e.shortDate);case"D":return b.t(e.longDate);case"F":return b.t(e.fullDateTime);case"m":return b.t(e.monthDay);case"r":return b.t(e.rfc1123);case"s":return b.t(e.sortableDateTime);case"t":return b.t(e.shortTime);case"T":return b.t(e.longTime);case"u":return b.t(e.universalSortableDateTime);case"y":return b.t(e.yearMonth)}}var f=function(a){switch(1*a){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th"}};return a?a.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g,function(a){if("\\"===a.charAt(0))return a.replace("\\","");switch(b.h=b.getHours,a){case"hh":return d(b.h()<13?0===b.h()?12:b.h():b.h()-12);case"h":return b.h()<13?0===b.h()?12:b.h():b.h()-12;case"HH":return d(b.h());case"H":return b.h();case"mm":return d(b.getMinutes());case"m":return b.getMinutes();case"ss":return d(b.getSeconds());case"s":return b.getSeconds();case"yyyy":return d(b.getFullYear(),4);case"yy":return d(b.getFullYear());case"dddd":return c.dayNames[b.getDay()];case"ddd":return c.abbreviatedDayNames[b.getDay()];case"dd":return d(b.getDate());case"d":return b.getDate();case"MMMM":return c.monthNames[b.getMonth()];case"MMM":return c.abbreviatedMonthNames[b.getMonth()];case"MM":return d(b.getMonth()+1);case"M":return b.getMonth()+1;case"t":return b.h()<12?c.amDesignator.substring(0,1):c.pmDesignator.substring(0,1);case"tt":return b.h()<12?c.amDesignator:c.pmDesignator;case"S":return f(b.getDate());default:return a}}):this._toString()}}(),function(){var a=Date,b=a.prototype,c=a.CultureInfo,d=Number.prototype;b._orient=1,b._nth=null,b._is=!1,b._same=!1,b._isSecond=!1,d._dateElement="day",b.next=function(){return this._orient=1,this},a.next=function(){return a.today().next()},b.last=b.prev=b.previous=function(){return this._orient=-1,this},a.last=a.prev=a.previous=function(){return a.today().last()},b.is=function(){return this._is=!0,this},b.same=function(){return this._same=!0,this._isSecond=!1,this},b.today=function(){return this.same().day()},b.weekday=function(){return this._is?(this._is=!1,!this.is().sat()&&!this.is().sun()):!1},b.at=function(b){return"string"==typeof b?a.parse(this.toString("d")+" "+b):this.set(b)},d.fromNow=d.after=function(a){var b={};return b[this._dateElement]=this,(a?a.clone():new Date).add(b)},d.ago=d.before=function(a){var b={};return b[this._dateElement]=-1*this,(a?a.clone():new Date).add(b)};var j,e="sunday monday tuesday wednesday thursday friday saturday".split(/\s/),f="january february march april may june july august september october november december".split(/\s/),g="Millisecond Second Minute Hour Day Week Month Year".split(/\s/),h="Milliseconds Seconds Minutes Hours Date Week Month FullYear".split(/\s/),i="final first second third fourth fifth".split(/\s/);b.toObject=function(){for(var a={},b=0;bd)throw new RangeError(a.getDayName(b)+" does not occur "+c+" times in the month of "+a.getMonthName(d.getMonth())+" "+d.getFullYear()+".");return this}return this.moveToDayOfWeek(b,this._orient)}},l=function(b){return function(){var d=a.today(),e=b-d.getDay();return 0===b&&1===c.firstDayOfWeek&&0!==d.getDay()&&(e+=7),d.addDays(e)}},m=0;m-1;f--){if(d=g[f].toLowerCase(),b[d]!=c[d])return!1;if(e==d)break}return!0}return"s"!=a.substring(a.length-1)&&(a+="s"),this["add"+a](this._orient)}},r=function(a){return function(){return this._dateElement=a,this}},s=0;s0&&!l)try{i=d.call(this,g[1])}catch(o){l=!0}else l=!0;if(l||0!==i[1].length||(l=!0),!l){for(var p=[],q=0;q0&&(j[0]=j[0].concat(h[0]),j[1]=h[1])}if(j[1].length1?b=Array.prototype.slice.call(arguments):arguments[0]instanceof Array&&(b=arguments[0]),!b)return a.apply(null,arguments);for(var d=0,e=b.shift();d2?b:b+(b+2e3a.getDaysInMonth(this.year,this.month))throw new RangeError(this.day+" is not a valid value for days.");var e=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);return this.timezone?e.set({timezone:this.timezone}):this.timezoneOffset&&e.set({timezoneOffset:this.timezoneOffset}),e},finish:function(b){if(b=b instanceof Array?d(b):[b],0===b.length)return null;for(var c=0;c=0;c--)a[c].className=a[c].className.replace(/introjs-fixParent/g,"").replace(/^\s+|\s+$/g,"");window.removeEventListener?window.removeEventListener("keydown",this._onKeyDown,!0):document.detachEvent&&document.detachEvent("onkeydown",this._onKeyDown),this._currentStep=void 0}}function A(a,b,c){if(b.style.top=null,b.style.right=null,b.style.bottom=null,b.style.left=null,this._introItems[this._currentStep]){var d="",d=this._introItems[this._currentStep],d="string"==typeof d.tooltipClass?d.tooltipClass:this._options.tooltipClass;switch(b.className=("introjs-tooltip "+d).replace(/^\s+|\s+$/g,""),this._introItems[this._currentStep].position){case"top":b.style.left="15px",b.style.top="-"+(p(b).height+10)+"px",c.className="introjs-arrow bottom";break;case"right":b.style.left=p(a).width+20+"px",c.className="introjs-arrow left";break;case"left":1==this._options.showStepNumbers&&(b.style.top="15px"),b.style.right=p(a).width+20+"px",c.className="introjs-arrow right";break;default:b.style.bottom="-"+(p(b).height+10)+"px",c.className="introjs-arrow top"}}}function w(a){if(a&&this._introItems[this._currentStep]){var b=p(this._introItems[this._currentStep].element);a.setAttribute("style","width: "+(b.width+10)+"px; height:"+(b.height+10)+"px; top:"+(b.top-5)+"px;left: "+(b.left-5)+"px;")}}function z(a){var b;"undefined"!=typeof this._introChangeCallback&&this._introChangeCallback.call(this,a.element);var c=this,d=document.querySelector(".introjs-helperLayer");if(p(a.element),null!=d){var f=d.querySelector(".introjs-helperNumberLayer"),B=d.querySelector(".introjs-tooltiptext"),j=d.querySelector(".introjs-arrow"),n=d.querySelector(".introjs-tooltip"),h=d.querySelector(".introjs-skipbutton"),m=d.querySelector(".introjs-prevbutton"),k=d.querySelector(".introjs-nextbutton");n.style.opacity=0,w.call(c,d);var l=document.querySelectorAll(".introjs-fixParent");if(l&&0=0;b--)l[b].className=l[b].className.replace(/introjs-fixParent/g,"").replace(/^\s+|\s+$/g,"");b=document.querySelector(".introjs-showElement"),b.className=b.className.replace(/introjs-[a-zA-Z]+/g,"").replace(/^\s+|\s+$/g,""),c._lastShowElementTimer&&clearTimeout(c._lastShowElementTimer),c._lastShowElementTimer=setTimeout(function(){null!=f&&(f.innerHTML=a.step),B.innerHTML=a.intro,A.call(c,a.element,n,j),d.querySelector(".introjs-bullets li > a.active").className="",d.querySelector('.introjs-bullets li > a[data-stepnumber="'+a.step+'"]').className="active",n.style.opacity=1},350)}else{var h=document.createElement("div"),l=document.createElement("div"),g=document.createElement("div"),m=document.createElement("div"),k=document.createElement("div"),e=document.createElement("div");h.className="introjs-helperLayer",w.call(c,h),this._targetElement.appendChild(h),l.className="introjs-arrow",m.className="introjs-tooltiptext",m.innerHTML=a.intro,k.className="introjs-bullets",!1===this._options.showBullets&&(k.style.display="none");var q=document.createElement("ul");b=0;for(var v=this._introItems.length;v>b;b++){var s=document.createElement("li"),r=document.createElement("a");r.onclick=function(){c.goToStep(this.getAttribute("data-stepnumber"))},0===b&&(r.className="active"),r.href="javascript:void(0);",r.innerHTML=" ",r.setAttribute("data-stepnumber",this._introItems[b].step),s.appendChild(r),q.appendChild(s)}k.appendChild(q),e.className="introjs-tooltipbuttons",!1===this._options.showButtons&&(e.style.display="none"),g.className="introjs-tooltip",g.appendChild(m),g.appendChild(k),1==this._options.showStepNumbers&&(b=document.createElement("span"),b.className="introjs-helperNumberLayer",b.innerHTML=a.step,h.appendChild(b)),g.appendChild(l),h.appendChild(g),k=document.createElement("a"),k.onclick=function(){c._introItems.length-1!=c._currentStep&&t.call(c)},k.href="javascript:void(0);",k.innerHTML=this._options.nextLabel,m=document.createElement("a"),m.onclick=function(){0!=c._currentStep&&x.call(c)},m.href="javascript:void(0);",m.innerHTML=this._options.prevLabel,h=document.createElement("a"),h.className="introjs-button introjs-skipbutton",h.href="javascript:void(0);",h.innerHTML=this._options.skipLabel,h.onclick=function(){c._introItems.length-1==c._currentStep&&"function"==typeof c._introCompleteCallback&&c._introCompleteCallback.call(c),c._introItems.length-1!=c._currentStep&&"function"==typeof c._introExitCallback&&c._introExitCallback.call(c),u.call(c,c._targetElement)},e.appendChild(h),1g)&&(b.className+=" introjs-fixParent"),b=b.parentNode;b=a.element.getBoundingClientRect(),!(0<=b.top&&0<=b.left&&b.bottom+80<=window.innerHeight&&b.right<=window.innerWidth)&&!0===this._options.scrollToElement&&(g=a.element.getBoundingClientRect(),b=void 0!=window.innerWidth?window.innerHeight:document.documentElement.clientHeight,l=g.bottom-(g.bottom-g.top),g=g.bottom-b,0>l||a.element.clientHeight>b?window.scrollBy(0,l-30):window.scrollBy(0,g+100)),"undefined"!=typeof this._introAfterChangeCallback&&this._introAfterChangeCallback.call(this,a.element)}function y(a,b){var c="";return a.currentStyle?c=a.currentStyle[b]:document.defaultView&&document.defaultView.getComputedStyle&&(c=document.defaultView.getComputedStyle(a,null).getPropertyValue(b)),c&&c.toLowerCase?c.toLowerCase():c}function C(a){var b=document.createElement("div"),c="",d=this;if(b.className="introjs-overlay","body"===a.tagName.toLowerCase())c+="top: 0;bottom: 0; left: 0;right: 0;position: fixed;",b.setAttribute("style",c);else{var f=p(a);f&&(c+="width: "+f.width+"px; height:"+f.height+"px; top:"+f.top+"px;left: "+f.left+"px;",b.setAttribute("style",c))}return a.appendChild(b),b.onclick=function(){1==d._options.exitOnOverlayClick&&(u.call(d,a),void 0!=d._introExitCallback&&d._introExitCallback.call(d))},setTimeout(function(){c+="opacity: .8;",b.setAttribute("style",c)},10),!0}function p(a){var b={};b.width=a.offsetWidth,b.height=a.offsetHeight;for(var c=0,d=0;a&&!isNaN(a.offsetLeft)&&!isNaN(a.offsetTop);)c+=a.offsetLeft,d+=a.offsetTop,a=a.offsetParent;return b.top=d,b.left=c,b}var v=function(a){if("object"==typeof a)return new e(a);if("string"==typeof a){if(a=document.querySelector(a))return new e(a);throw Error("There is no element with given selector.")}return new e(document.body)};return v.version="0.7.1",v.fn=e.prototype={clone:function(){return new e(this)},setOption:function(a,b){return this._options[a]=b,this},setOptions:function(a){var d,b=this._options,c={};for(d in b)c[d]=b[d];for(d in a)c[d]=a[d];return this._options=c,this},start:function(){a:{var a=this._targetElement,b=[],c=this;if(this._options.steps)for(var d=[],f=0,d=this._options.steps.length;d>f;f++){var e=s(this._options.steps[f]);e.step=b.length+1,"string"==typeof e.element&&(e.element=document.querySelector(e.element)),null!=e.element&&b.push(e)}else{if(d=a.querySelectorAll("*[data-intro]"),1>d.length)break a;for(f=0,e=d.length;e>f;f++){var j=d[f],n=parseInt(j.getAttribute("data-step"),10);n>0&&(b[n-1]={element:j,intro:j.getAttribute("data-intro"),step:parseInt(j.getAttribute("data-step"),10),tooltipClass:j.getAttribute("data-tooltipClass"),position:j.getAttribute("data-position")||this._options.tooltipPosition})}for(f=n=0,e=d.length;e>f;f++)if(j=d[f],null==j.getAttribute("data-step")){for(;"undefined"!=typeof b[n];)n++;b[n]={element:j,intro:j.getAttribute("data-intro"),step:n+1,tooltipClass:j.getAttribute("data-tooltipClass"),position:j.getAttribute("data-position")||this._options.tooltipPosition}}}for(f=[],d=0;d0?$scope.newCollection.entity&&$scope.newCollection.entity.length>0?$scope.validateEntityData(!0)&&(ug.createCollectionWithEntity($scope.newCollection.name,$scope.newCollection.entity),ug.getTopCollections(),$scope.hideModal(modalId)):$rootScope.$broadcast("alert","error","You must specify JSON data for the new entity."):$rootScope.$broadcast("alert","error","You must specify a collection name.")},$scope.addToPath=function(uuid){$scope.data.queryPath="/"+$rootScope.queryCollection._type+"/"+uuid},$scope.removeFromPath=function(){$scope.data.queryPath="/"+$rootScope.queryCollection._type},$scope.isDeep=function(item){return"[object Object]"===Object.prototype.toString.call(item)},$scope.loadCollection=function(type){$scope.data.queryPath="/"+type.substring(1,type.length),$scope.data.searchString="",$scope.data.queryLimit="",$scope.data.body='{ "name":"value" }',$scope.selectGET(),$scope.applyScope(),$scope.run()},$scope.selectGET=function(){$scope.queryBodyDisplay="none",$scope.queryLimitDisplay="block",$scope.queryStringDisplay="block",$scope.verb="GET"},$scope.selectPOST=function(){$scope.queryBodyDisplay="block",$scope.queryLimitDisplay="none",$scope.queryStringDisplay="none",$scope.verb="POST"},$scope.selectPUT=function(){$scope.queryBodyDisplay="block",$scope.queryLimitDisplay="block",$scope.queryStringDisplay="block",$scope.verb="PUT"},$scope.selectDELETE=function(){$scope.queryBodyDisplay="none",$scope.queryLimitDisplay="block",$scope.queryStringDisplay="block",$scope.verb="DELETE"},$scope.validateEntityData=function(skipMessage){var queryBody=$scope.newCollection.entity;try{queryBody=JSON.parse(queryBody)}catch(e){return $rootScope.$broadcast("alert","error","JSON is not valid"),!1}return queryBody=JSON.stringify(queryBody,null,2),!skipMessage&&$rootScope.$broadcast("alert","success","JSON is valid"),$scope.newCollection.entity=queryBody,!0},$scope.validateJson=function(skipMessage){var queryBody=$scope.data.queryBody;try{queryBody=JSON.parse(queryBody)}catch(e){return $rootScope.$broadcast("alert","error","JSON is not valid"),!1}return queryBody=JSON.stringify(queryBody,null,2),!skipMessage&&$rootScope.$broadcast("alert","success","JSON is valid"),$scope.data.queryBody=queryBody,!0},$scope.isValidJSON=function(data){try{data=JSON.parse(data)}catch(e){return!1}return!0},$scope.formatJSON=function(data){try{data=JSON.parse(data)}catch(e){return data}return JSON.stringify(data,null,2)},$scope.saveEntity=function(entity){if(!$scope.validateJson())return!1;var queryBody=entity._json;queryBody=JSON.parse(queryBody),$rootScope.selectedEntity.set(),$rootScope.selectedEntity.set(queryBody),$rootScope.selectedEntity.set("type",entity._data.type),$rootScope.selectedEntity.set("uuid",entity._data.uuid),$rootScope.selectedEntity.save(function(err,data){err?$rootScope.$broadcast("alert","error","error: "+data.error_description):$rootScope.$broadcast("alert","success","entity saved")})},$scope.run=function(){$rootScope.queryCollection="";var verb=$scope.verb;runQuery(verb)},$scope.hasProperty=function(prop){var retval=!1;return"undefined"!=typeof $rootScope.queryCollection._list&&angular.forEach($rootScope.queryCollection._list,function(value){retval||value._data[prop]&&(retval=!0)}),retval},$scope.resetNextPrev=function(){$scope.previous_display="none",$scope.next_display="none"},$scope.checkNextPrev=function(){$scope.resetNextPrev(),$rootScope.queryCollection.hasPreviousPage()&&($scope.previous_display="default"),$rootScope.queryCollection.hasNextPage()&&($scope.next_display="default")},$scope.selectEntity=function(uuid,addToPath){$rootScope.selectedEntity=$rootScope.queryCollection.getEntityByUUID(uuid),addToPath?$scope.addToPath(uuid):$scope.removeFromPath()},$scope.getJSONView=function(entity){var tempjson=entity.get(),queryBody=JSON.stringify(tempjson,null,2);queryBody=JSON.parse(queryBody),delete queryBody.metadata,delete queryBody.uuid,delete queryBody.created,delete queryBody.modified,delete queryBody.type,$scope.queryBody=JSON.stringify(queryBody,null,2)},$scope.getPrevious=function(){$rootScope.queryCollection.getPreviousPage(function(err){err&&$rootScope.$broadcast("alert","error","error getting previous page of data"),$scope.checkNextPrev(),$scope.applyScope()})},$scope.getNext=function(){$rootScope.queryCollection.getNextPage(function(err){err&&$rootScope.$broadcast("alert","error","error getting next page of data"),$scope.checkNextPrev(),$scope.applyScope()})},init(),$rootScope.queryCollection=$rootScope.queryCollection||{},$rootScope.selectedEntity={},$rootScope.queryCollection&&$rootScope.queryCollection._type&&($scope.loadCollection($rootScope.queryCollection._type),$scope.setDisplayType()),ug.getTopCollections(),$scope.resetNextPrev()}]),AppServices.Controllers.controller("EntityCtrl",["ug","$scope","$rootScope","$location",function(ug,$scope,$rootScope,$location){if(!$rootScope.selectedEntity)return void $location.path("/data");$scope.entityUUID=$rootScope.selectedEntity.get("uuid"),$scope.entityType=$rootScope.selectedEntity.get("type");var tempjson=$rootScope.selectedEntity.get(),queryBody=JSON.stringify(tempjson,null,2);queryBody=JSON.parse(queryBody),delete queryBody.metadata,delete queryBody.uuid,delete queryBody.created,delete queryBody.modified,delete queryBody.type,$scope.queryBody=JSON.stringify(queryBody,null,2),$scope.validateJson=function(){var queryBody=$scope.queryBody;try{queryBody=JSON.parse(queryBody)}catch(e){return $rootScope.$broadcast("alert","error","JSON is not valid"),!1}return queryBody=JSON.stringify(queryBody,null,2),$rootScope.$broadcast("alert","success","JSON is valid"),$scope.queryBody=queryBody,!0},$scope.saveEntity=function(){if(!$scope.validateJson())return!1;var queryBody=$scope.queryBody;queryBody=JSON.parse(queryBody),$rootScope.selectedEntity.set(),$rootScope.selectedEntity.set(queryBody),$rootScope.selectedEntity.set("type",$scope.entityType),$rootScope.selectedEntity.set("uuid",$scope.entityUUID),$rootScope.selectedEntity.save(function(err,data){err?$rootScope.$broadcast("alert","error","error: "+data.error_description):$rootScope.$broadcast("alert","success","entity saved")})}}]),AppServices.Directives.directive("balloon",["$window","$timeout",function($window,$timeout){return{restrict:"ECA",scope:"=",template:'
    ',replace:!0,transclude:!0,link:function(scope,lElement,attrs){scope.direction=attrs.direction;var runScroll=!0,windowEl=angular.element($window);windowEl.on("scroll",function(){runScroll&&(lElement.addClass("fade-out"),$timeout(function(){lElement.addClass("hide")},1e3),runScroll=!1)})}}}]),AppServices.Directives.directive("bsmodal",["$rootScope",function($rootScope){return{restrict:"ECA",scope:{title:"@title",buttonid:"=buttonid",footertext:"=footertext",closelabel:"=closelabel"},transclude:!0,templateUrl:"dialogs/modal.html",replace:!0,link:function(scope,lElement,attrs,parentCtrl){scope.title=attrs.title,scope.footertext=attrs.footertext,scope.closelabel=attrs.closelabel,scope.close=attrs.close,scope.extrabutton=attrs.extrabutton,scope.extrabuttonlabel=attrs.extrabuttonlabel,scope.buttonId=attrs.buttonid,scope.closeDelegate=function(attr){scope.$parent[attr](attrs.id,scope)},scope.extraDelegate=function(attr){scope.dialogForm.$valid?(console.log(parentCtrl),scope.$parent[attr](attrs.id)):$rootScope.$broadcast("alert","error","Please check your form input and resubmit.")}}}}]),angular.module("appservices").run(["$templateCache",function($templateCache){"use strict";$templateCache.put("activities/activities.html",'
    \n\n
    \n
    \n

    \n 📱 Activities\n

    \n
    \n
    \n\n
    \n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    DateUserContentVerbUUID
    {{formatDate(activity.created)}}{{activity.actor.displayName}}{{activity.content}}{{activity.verb}}{{activity.uuid}}
    \n
    \n
    \n'),$templateCache.put("app-overview/app-overview.html",'
    \n\n
    \n\n \n
    \n

    {{currentApp}}

    \n
    \n
    \n\n
    \n \n \n \n \n \n \n \n \n \n
    PathTitle
    {{v.title}}{{v.count}}
    \n
    \n\n
    \n
    \n'),$templateCache.put("app-overview/doc-includes/android.html",'

    1. Integrate the SDK into your project

    \n\n

    You can integrate Apigee features into your app by including the\n SDK in your project.  You can do one of the following:

    \n\n\n\n
    \n
    \n \n

    If you\'ve already got an Android project, you can\n integrate the Apigee SDK into your project as you\n normally would:

    \n \n
    \n

    \n Add\n apigee-android-<version>.jar\n to your class path by doing the following:\n

    \n\n

    Android 4.0 (or later) projects

    \n

    \n Copy the jar file into the\n /libs\n folder in your project.\n

    \n\n

    Android 3.0 (or earlier) projects

    \n
      \n
    1. In the Eclipse Package Explorer,\n select your application\'s project folder.\n
    2. \n
    3. Click the File > Properties menu.\n
    4. \n
    5. In the Java Build Path section, click\n the Libraries tab, click Add\n External JARs.\n
    6. \n
    7. Browse to apigee-android-<version>.jar,\n then click Open.\n
    8. \n
    9. Order the apigee-android-<version>.jar\n at the top of the class path:\n
        \n
      1. In the Eclipse Package Explorer,\n select your application\'s project folder.\n
      2. \n
      3. Click the File >\n Properties menu.\n
      4. \n
      5. In the properties dialog, in the Java\n Build Path section, click the Order\n and Export tab.\n
      6. \n
      7. \n

        \n IMPORTANT: Select the checkbox for\n apigee-android-<version>.jar\n , then click the Top button.\n

        \n
      8. \n
      \n
    10. \n
    \n
    \n

    Applications using Ant

    \n

    \n If you are using Ant to build your application, you must also\n copy\n apigee-android-<version>.jar\n to the\n /libs\n folder in your application.\n

    \n
    \n
    \n
    \n
    \n \n

    If you don\'t have a project yet, you can begin by using\n the project template included with the SDK. The template includes\n support for SDK features.

    \n
      \n
    • Locate the project template in the expanded SDK. It\n should be at the following location:
      <sdk_root>/new-project-template
      \n
    • \n
    \n
    \n
    \n

    2. Update permissions in AndroidManifest.xml

    \n

    \n Add the following Internet permissions to your application\'s\n AndroidManifest.xml\n file if they have not already been added. Note that with the exception\n of INTERNET, enabling all other permissions are optional.\n

    \n
    \n<uses-permission android:name="android.permission.INTERNET" />\n<uses-permission android:name="android.permission.READ_PHONE_STATE" />\n<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />\n<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />\n<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />\n
    \n

    3. Initialize the SDK

    \n

    \n To initialize the App Services SDK, you must instantiate the\n ApigeeClient\n class. There are multiple ways to handle this step, but we recommend\n that you do the following:\n

    \n
      \n
    1. Subclass the Application class, and add an\n instance variable for the ApigeeClient to it, along\n with getter and setter methods.
      \npublic class YourApplication extends Application\n{\n        \n        private ApigeeClient apigeeClient;\n        \n        public YourApplication()\n        {\n                this.apigeeClient = null;\n        }\n        \n        public ApigeeClient getApigeeClient()\n        {\n                return this.apigeeClient;\n        }\n        \n        public void setApigeeClient(ApigeeClient apigeeClient)\n        {\n                this.apigeeClient = apigeeClient;\n        }\n}			\n		
      \n
    2. \n
    3. Declare the Application subclass in your AndroidManifest.xml.\n For example:
      \n<application>\n    android:allowBackup="true"\n    android:icon="@drawable/ic_launcher"\n    android:label="@string/app_name"\n    android:name=".YourApplication"\n	…\n</application>			\n		
      \n
    4. \n
    5. Instantiate the ApigeeClient class in the onCreate\n method of your first Activity class:
      \nimport com.apigee.sdk.ApigeeClient;\n\n@Override\nprotected void onCreate(Bundle savedInstanceState) {\n    super.onCreate(savedInstanceState);		\n	\n	String ORGNAME = "{{currentOrg}}";\n	String APPNAME = "{{currentApp}}";\n	\n	ApigeeClient apigeeClient = new ApigeeClient(ORGNAME,APPNAME,this.getBaseContext());\n\n	// hold onto the ApigeeClient instance in our application object.\n	YourApplication yourApp = (YourApplication) getApplication;\n	yourApp.setApigeeClient(apigeeClient);			\n}\n		
      \n

      \n This will make the instance of\n ApigeeClient\n available to your\n Application\n class.\n

      \n
    6. \n
    \n

    4. Import additional SDK classes

    \n

    The following classes will enable you to call common SDK methods:

    \n
    \nimport com.apigee.sdk.data.client.DataClient; //App Services data methods\nimport com.apigee.sdk.apm.android.MonitoringClient; //App Monitoring methods\nimport com.apigee.sdk.data.client.callbacks.ApiResponseCallback; //API response handling\nimport com.apigee.sdk.data.client.response.ApiResponse; //API response object\n
    \n\n

    5. Verify SDK installation

    \n\n

    \n Once initialized, App Services will also automatically instantiate the\n MonitoringClient\n class and begin logging usage, crash and error metrics for your app.\n

    \n

    \n screenshot of data in admin portal\n

    \n

    \n To verify that the SDK has been properly initialized, run your app,\n then go to \'Monitoring\' > \'App Usage\' in the App Services admin portal\n to verify that data is being sent.\n

    \n
    It may take up to two minutes for data to\n appear in the admin portal after you run your app.
    \n\n

    Installation complete! Try these next steps

    \n
      \n
    • \n

      \n Call additional SDK methods in your code\n

      \n

      \n The\n DataClient\n and\n MonitoringClient\n classes are also automatically instantiated for you, and\n accessible with the following accessors:\n

      \n
        \n
      • DataClient dataClient = apigeeClient.getDataClient();
        \n

        Use this object to access the data methods of the App\n Services SDK, including those for push notifications, data\n store, and geolocation.

      • \n
      • MonitoringClient monitoringClient = apigeeClient.getMonitoringClient();
        \n

        Use this object to access the app configuration and\n monitoring methods of the App Services SDK, including advanced\n logging, and A/B testing.

      • \n
      \n
    • \n
    • \n

      \n Add App Services features to your app\n

      \n

      With App Services you can quickly add valuable features to\n your mobile or web app, including push notifications, a custom\n data store, geolocation and more. Check out these links to get\n started with a few of our most popular features:

      \n
        \n
      • Push notifications:\n Send offers, alerts and other messages directly to user devices\n to dramatically increase engagement. With App Services you can\n send 10 million push notification per month for free!
      • \n
      • App Monitoring: When you initialize the\n App Services SDK, a suite of valuable, customizable\n application monitoring features are automatically enabled that\n deliver the data you need to fine tune performance, analyze\n issues, and improve user experience.\n
          \n
        • App Usage\n Monitoring: Visit the App Services admin\n portal to view usage data for your app, including data on\n device models, platforms and OS versions running your app.
        • \n
        • API\n Performance Monitoring: Network performance is key to a\n solid user experience. In the App Services admin\n portal you can view key metrics, including response time,\n number of requests and raw API request logs.
        • \n
        • Error &\n Crash Monitoring: Get alerted to any errors or crashes,\n then view them in the App\n Services admin portal, where you can also analyze raw\n error and crash logs.
        • \n
      • \n
      • Geolocation: Target\n users or return result sets based on user location to keep your\n app highly-relevant.
      • \n
      • Data storage:\n Store all your application data on our high-availability\n infrastructure, and never worry about dealing with a database\n ever again.
      • \n
      • User management and\n authentication: Every app needs users. Use App Services to\n easily implement user registration, as well as OAuth\n 2.0-compliant login and authentication.
      • \n
      \n
    • \n
    • \n

      \n Check out the sample apps\n

      \n

      The SDK includes samples that illustrate\n Apigee features. You\'ll find the samples in the following\n location in your SDK download:

      \napigee-android-sdk-<version>\n	...\n	/samples\n		
      \n \n
      \n

      The samples include the following:

      \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
      SampleDescription
      booksAn app for storing a list of books that shows\n Apigee database operations such as reading, creating, and\n deleting.
      messageeAn app for sending and receiving messages that\n shows Apigee database operations (reading, creating).
      pushAn app that uses the push feature to send\n notifications to the devices of users who have subscribed\n for them.
      \n
      \n
    • \n
    \n'),$templateCache.put("app-overview/doc-includes/ios.html",'

    1. Integrate ApigeeiOSSDK.framework

    \n\n\n\n
    \n
    \n

    If you\'ve already got an Xcode iOS project, add it into\n your project as you normally would.

    \n
    \n Details\n
    \n
    \n
      \n
    1. \n

      Locate the SDK framework file so you can add it to your\n project. For example, you\'ll find the file at the following\n path:

      \n<sdk_root>/bin/ApigeeiOSSDK.framework
      \n
    2. \n
    3. In the Project Navigator, click on\n your project file, and then the Build Phases\n tab. Expand Link Binary With Libraries.\n
    4. \n
    5. Link the Apigee iOS SDK into your project.\n
        \n
      • Drag ApigeeiOSSDK.framework into the Frameworks\n group created by Xcode.
      • \n
      \n

      OR

      \n
        \n
      1. At the bottom of the Link Binary\n With Libraries group, click the +\n button. Then click Add Other.\n
      2. \n
      3. Navigate to the directory that contains\n ApigeeiOSSDK.framework, and choose the\n ApigeeiOSSDK.framework folder.
      4. \n
      \n
    6. \n
    \n
    \n
    \n
    \n \n

    If you\'re starting with a clean slate (you don\'t have\n a project yet), you can begin by using the project template\n included with the SDK. The template includes support for SDK\n features.

    \n
      \n
    1. \n

      Locate the project template in the expanded SDK. It\n should be at the following location:

      \n<sdk_root>/new-project-template
      \n
    2. \n
    3. In the project template directory, open the project\n file: Apigee App Services iOS Template.xcodeproj.
    4. \n
    5. Get acquainted with the template by looking at its readme\n file.
    6. \n
    \n
    \n
    \n

    2. Add required iOS frameworks

    \n

    \n Ensure that the following iOS frameworks are part of your project. To\n add them, under the Link Binary With Libraries group,\n click the + button, type the name of the framework\n you want to add, select the framework found by Xcode, then click Add.\n

    \n
      \n
    • QuartzCore.framework
    • \n
    • CoreLocation.framework
    • \n
    • CoreTelephony.framework 
    • \n
    • Security.framework
    • \n
    • SystemConfiguration.framework
    • \n
    • UIKit.framework
    • \n
    \n

    3. Update \'Other Linker Flags\'

    \n

    \n In the Build Settings panel, add the following under\n Other Linker Flags:\n

    \n
    \n-ObjC -all_load
    \n

    \n Confirm that flags are set for both DEBUG and RELEASE.\n

    \n

    4. Initialize the SDK

    \n

    \n The ApigeeClient class initializes the App Services SDK. To\n do this you will need your organization name and application name,\n which are available in the Getting Started tab of the App Service admin portal,\n under Mobile SDK Keys.\n

    \n
      \n
    1. Import the SDK\n

      Add the following to your source code to import the SDK:

      \n#import <ApigeeiOSSDK/Apigee.h>
      \n
    2. \n
    3. \n

      \n Declare the following properties in\n AppDelegate.h\n :\n

      \n@property (strong, nonatomic) ApigeeClient *apigeeClient; \n@property (strong, nonatomic) ApigeeMonitoringClient *monitoringClient;\n@property (strong, nonatomic) ApigeeDataClient *dataClient;	\n		
      \n
    4. \n
    5. \n

      \n Instantiate the\n ApigeeClient\n class inside the \n didFinishLaunching\n method of\n AppDelegate.m\n :\n

      \n//Replace \'AppDelegate\' with the name of your app delegate class to instantiate it\nAppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];\n\n//Sepcify your App Services organization and application names\nNSString *orgName = @"{{currentOrg}}";\nNSString *appName = @"{{currentApp}}";\n\n//Instantiate ApigeeClient to initialize the SDK\nappDelegate.apigeeClient = [[ApigeeClient alloc]\n                            initWithOrganizationId:orgName\n                            applicationId:appName];\n                            \n//Retrieve instances of ApigeeClient.monitoringClient and ApigeeClient.dataClient\nself.monitoringClient = [appDelegate.apigeeClient monitoringClient]; \nself.dataClient = [appDelegate.apigeeClient dataClient]; \n		
      \n
    6. \n
    \n\n

    5. Verify SDK installation

    \n\n

    \n Once initialized, App Services will also automatically instantiate the\n ApigeeMonitoringClient\n class and begin logging usage, crash and error metrics for your app.\n

    \n\n

    \n To verify that the SDK has been properly initialized, run your app,\n then go to \'Monitoring\' > \'App Usage\' in the App Services admin portal\n to verify that data is being sent.\n

    \n

    \n screenshot of data in admin portal\n

    \n
    It may take up to two minutes for data to\n appear in the admin portal after you run your app.
    \n\n

    Installation complete! Try these next steps

    \n
      \n
    • \n

      \n Call additional SDK methods in your code\n

      \n

      \n Create an instance of the AppDelegate class, then use\n appDelegate.dataClient\n or\n appDelegate.monitoringClient\n to call SDK methods:\n

      \n
      \n Details\n
      \n
      \n
        \n
      • appDelegate.dataClient: Used to access the\n data methods of the App Services SDK, including those for push\n notifications, data store, and geolocation.
      • \n
      • appDelegate.monitoringClient: Used to\n access the app configuration and monitoring methods of the App\n Services SDK, including advanced logging, and A/B testing.
      • \n
      \n

      Example

      \n

      For example, you could create a new entity with the\n following:

      \n
      \nAppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];\nApigeeClientResponse *response = [appDelegate.dataClient createEntity:entity];\n			
      \n
      \n\n
    • \n
    • \n

      \n Add App Services features to your app\n

      \n

      With App Services you can quickly add valuable features to\n your mobile or web app, including push notifications, a custom\n data store, geolocation and more. Check out these links to get\n started with a few of our most popular features:

      \n
        \n
      • Push notifications:\n Send offers, alerts and other messages directly to user devices\n to dramatically increase engagement. With App Services you can\n send 10 million push notification per month for free!
      • \n
      • Geolocation: Target\n users or return result sets based on user location to keep your\n app highly-relevant.
      • \n
      • Data storage:\n Store all your application data on our high-availability\n infrastructure, and never worry about dealing with a database\n ever again.
      • \n
      • User management and\n authentication: Every app needs users. Use App Services to\n easily implement user registration, as well as OAuth\n 2.0-compliant login and authentication.
      • \n
      \n
    • \n
    • \n

      \n Check out the sample apps\n

      \n

      \n The SDK includes samples that illustrate Apigee features. To\n look at them, open the .xcodeproj file for each in Xcode. To get a\n sample app running, open its project file, then follow the steps\n described in the section, Add\n the SDK to an existing project.\n

      \n

      You\'ll find the samples in the following location in your SDK\n download:

      \napigee-ios-sdk-<version>\n    ...\n    /samples\n		
      \n
      \n Details\n
      \n
      \n

      The samples include the following:

      \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
      SampleDescription
      booksAn app for storing a list of books that shows\n Apigee database operations such as reading, creating, and\n deleting.
      messageeAn app for sending and receiving messages that\n shows Apigee database operations (reading, creating).
      pushAn app that uses the push feature to send\n notifications to the devices of users who have subscribed\n for them.
      \n
      \n

       

      \n
    • \n
    \n'),$templateCache.put("app-overview/doc-includes/javascript.html",'

    1. Import the SDK into your HTML

    \n\n

    \n To enable support for Apigee-related functions in your HTML, you\'ll\n need to include\n apigee.js\n in your app. To do this, add the following to the\n head\n block of your HTML:\n

    \n
    \n<script type="text/javascript" src="path/to/js/sdk/apigee.js"></script>\n
    \n

    2. Instantiate Apigee.Client

    \n

    Apigee.Client initializes the App Services SDK, and gives you\n access to all of the App Services SDK methods.

    \n

    You will need to pass a JSON object with the UUID or name for\n your App Services organization and application when you instantiate\n it.

    \n
    \n//Apigee account credentials, available in the App Services admin portal \nvar client_creds = {\n        orgName:\'{{currentOrg}}\',\n        appName:\'{{currentApp}}\'\n    }\n\n//Initializes the SDK. Also instantiates Apigee.MonitoringClient\nvar dataClient = new Apigee.Client(client_creds);  \n
    \n\n

    3. Verify SDK installation

    \n\n

    \n Once initialized, App Services will also automatically instantiate\n Apigee.MonitoringClient\n and begin logging usage, crash and error metrics for your app.\n

    \n\n

    \n To verify that the SDK has been properly initialized, run your app,\n then go to \'Monitoring\' > \'App Usage\' in the App Services admin portal\n to verify that data is being sent.\n

    \n

    \n screenshot of data in admin portal\n

    \n
    It may take up to two minutes for data to\n appear in the admin portal after you run your app.
    \n\n

    Installation complete! Try these next steps

    \n
      \n
    • \n

      \n Call additional SDK methods in your code\n

      \n

      \n Use\n dataClient\n or\n dataClient.monitor\n to call SDK methods:\n

      \n \n
      \n
        \n
      • dataClient: Used to access the data\n methods of the App Services SDK, including those for push\n notifications, data store, and geolocation.
      • \n
      • dataClient.monitor: Used to access the app\n configuration and monitoring methods of the App Services SDK,\n including advanced logging, and A/B testing.
      • \n
      \n
      \n
    • \n
    • \n

      \n Add App Services features to your app\n

      \n

      With App Services you can quickly add valuable features to\n your mobile or web app, including push notifications, a custom\n data store, geolocation and more. Check out these links to get\n started with a few of our most popular features:

      \n
        \n
      • Push notifications:\n Send offers, alerts and other messages directly to user devices\n to dramatically increase engagement. With App Services you can\n send 10 million push notification per month for free!
      • \n
      • Geolocation: Keep\n your app highly-relevant by targeting users or returning result\n sets based on user location.
      • \n
      • Data storage:\n Store all your application data on our high-availability\n infrastructure, and never worry about dealing with a database\n ever again.
      • \n
      • User management and\n authentication: Every app needs users. Use App Services to\n easily implement registration, login and OAuth 2.0-compliant\n authentication.
      • \n
      \n
    • \n
    • \n

      \n Check out the sample apps\n

      \n

      The SDK includes samples that illustrate\n Apigee features. To look at them, open the .xcodeproj file\n for each in Xcode. You\'ll find the samples in the following\n location in your SDK download:

      \napigee-javascript-sdk-master\n    ...\n    /samples		\n		
      \n \n
      \n

      The samples include the following:

      \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
      SampleDescription
      booksSample.htmlAn app for storing a list of books that shows\n Apigee database operations such as reading, creating, and\n deleting.
      messageeAn app for sending and receiving messages that\n shows Apigee database operations (reading, creating).
      monitoringSample.htmlShows basic configuration and initialization of the\n HTML5 app monitoring functionality. Works in browser,\n PhoneGap, Appcelerator, and Trigger.io.
      readmeSample.htmlA simple app for reading data from an Apigee\n database.
      \n
      \n
    • \n
    \n'),$templateCache.put("app-overview/doc-includes/net.html",'\n'),$templateCache.put("app-overview/doc-includes/node.html",''),$templateCache.put("app-overview/doc-includes/ruby.html",''),$templateCache.put("data/data.html",'
    \n\n \n
    \n
    \n \n
    \n \n

    \n
    \n
    \n
    \n
    \n\n\n
    \n
    \n \n
    \n \n

    \n
    \n
    \n \n { "name":"value" }\n
    \n Validate JSON\n

    \n
    \n
    \n
    \n
    \n\n
    \n \n
    \n\n
    \n
    \n (?)\n
      \n /{{entity.name}}\n \n
    \n\n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n \n \n \n CREATE     \n READ     \n UPDATE     \n DELETE (?)\n
    \n
    \n\n
    \n Path \n
    \n \n (?)\n
    \n
    \n \n
    \n Query\n
    \n (?)\n
    \n \n \n \n \n
    \n
    \n
    \n\n\n
    \n \n
    \n
    \n \n
    \n
    \n
    \n\n
    \n \n
    \n \n
    Validate JSON (?)\n
    \n
    \n
    \n
    \n (?)\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n \n\n \n\n \n \n\n\n\n"),$templateCache.put("data/display-generic.html",'\n \n
    \n
    \n
    \n
    \n\n (?)\n \n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n
    NameUUID
    \n {{entity._data.name}}{{entity._data.uuid}}{{entitySelected[$index]\n ? \'Hide\' : \'View\'}} Details
    \n\n\n

    Entity Detail

    \n\n\n
      \n
    • {{k}} : \n \n
        \n
      • {{k2}}\n : \n
          \n
        • {{k3}} :{{v3}}
        • \n
        {{v2}}\n
        \n
      • \n
      {{v}}\n \n
    • \n
    \n\n
    \n

    \n Edit Entity (?)\n

    \n
    \n \n
    Validate JSON\n \n
    \n
    \n
    No data found
    \n
    \n \n \n
    \n\n'),$templateCache.put("data/display-groups.html",''),$templateCache.put("data/display-roles.html",'roles---------------------------------\n\n'),$templateCache.put("data/display-users.html",'\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
     UsernameDisplay NameUUID 
    10#"><img src=x\n onerror=prompt(1);>bf9a95da-d508-11e2-bf44-236d2eee13a7Details
    \n'),$templateCache.put("data/entity.html",'
    \n\n

    Entity Detail

    \n \n
    \n
    \n Path \n
    {{entityType}}/{{entityUUID}}
    \n
    \n\n
    \n \n
    \n \n
    Validate\n JSON\n
    \n
    \n
    \n
    \n \n \n
    \n
    \n\n
    \n\n'),$templateCache.put("dialogs/modal.html",'\n'),$templateCache.put("global/insecure-banner.html",'
    \n\n
    \n
    \n Warning: This application has\n "sandbox" permissions and is not production ready. Please\n go to our security documentation to find out more.\n
    \n
    \n
    \n'),$templateCache.put("global/page-title.html",'
    \n\n
    \n
    \n

    \n {{icon}}{{title}}\n (need help?)\n

    \n
    \n
    \n \n

    Do you want to contact support? Support will get in touch with\n you as soon as possible.

    \n
    \n
    \n\n'),$templateCache.put("groups/groups-activities.html",'
    \n\n
    \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    DateContentVerbUUID
    {{activity.createdDate}}{{activity.content}}{{activity.verb}}{{activity.uuid}}
    \n
    \n\n\n
    \n'),$templateCache.put("groups/groups-details.html",'
    \n\n
    \n
    \n
    \n

    Group Information

    \n \n (?)
    Group Path \n (?)
    \n
    \n
    \n\n
    \n \n
    \n\n
    \n

    \n JSON Group Object (?)\n

    \n
    {{json}}
    \n
    \n
    \n
    \n\n\n
    \n'),$templateCache.put("groups/groups-members.html",'
    \n\n \n

    Are you sure you want to remove the users from the seleted\n group(s)?

    \n
    \n\n \n \n \n\n\n
    \n (?)\n \n \n
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    UsernameDisplay Name
    \n {{user.get(\'username\')}}{{user.get(\'name\')}}
    \n
    \n \n \n
    \n
    \n'),$templateCache.put("groups/groups-roles.html",'
    \n\n \n \n \n\n \n

    Are you sure you want to remove the group from the role(s)?

    \n
    \n\n\n
    \n (?)\n \n \n
    \n

    \n Roles (?)\n

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    Role NameRole title
    \n {{role._data.name}}{{role._data.title}}
    \n
    \n \n \n
    \n\n\n \n

    Are you sure you want to delete the permission(s)?

    \n
    \n\n\n \n

    \n Path: (?)\n

    \n
    \n \n GET (?)\n
    \n
    \n \n POST\n
    \n
    \n \n PUT\n
    \n
    \n \n DELETE\n
    \n
    \n\n\n
    \n (?)\n \n \n
    \n

    \n Permissions (?)\n

    \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    PathGETPOSTPUTDELETE
    \n {{permission.path}}{{permission.operations.get}}{{permission.operations.post}}{{permission.operations.put}}{{permission.operations.delete}}
    \n\n
    \n'),$templateCache.put("groups/groups-tabs.html",'
    \n\n
    \n\n
    \n
    \n

    \n 👥 Groups\n

    \n
    \n
    \n\n
    \n\n
    \n \n
    \n\n
    \n
    \n
    \n Group Path: {{selectedGroup.get(\'path\')}}\n
    \n
    \n Group Title: {{selectedGroup.get(\'title\')}}\n
    \n
    \n
    \n
    \n
    \n
    \n'),$templateCache.put("groups/groups.html",'
    \n\n
    \n \n\n
    \n \n
    \n
    \n \n
    \n \n (?)\n
    \n
    \n
    \n \n
    \n (?)\n
    \n
    \n
    \n
    \n\n \n

    Are you sure you want to delete the group(s)?

    \n
    \n\n\n
    \n
    \n
    \n \n \n \n \n \n (?)\n
    \n \n\n\n
    \n \n \n
    \n
    \n\n
    \n \n
  • \n 👥Users (?)\n
  • \n
  • \n Activities (?)\n
  • \n
  • \n 🌎Roles & Permissions (?)\n
  • \n \n \n \n \n\n'),$templateCache.put("login/forgot-password.html",'").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});a.fn.bgiframe&&c.bgiframe(),this.instances.push(c);return c},destroy:function(b){var c=a.inArray(b,this.instances);c!=-1&&this.oldInstances.push(this.instances.splice(c,1)[0]),this.instances.length===0&&a([document,window]).unbind(".dialog-overlay"),b.remove();var d=0;a.each(this.instances,function(){d=Math.max(d,this.css("z-index"))}),this.maxZ=d},height:function(){var b,c;if(a.browser.msie&&a.browser.version<7){b=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),c=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return b0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]!==e){var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0}},top:function(b,c){if(c.at[1]!==e){var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];if(!c||!c.ownerDocument)return null;if(b)return this.each(function(){a.offset.setOffset(this,b)});return h.call(this)}),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()}(jQuery),function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("
    ").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===b)return this._value();this._setOption("value",a);return this},_setOption:function(b,c){b==="value"&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;typeof a!="number"&&(a=0);return Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.18"})}(jQuery),function(a,b){var c=5;a.widget("ui.slider",a.ui.mouse,{widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var b=this,d=this.options,e=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),f="",g=d.values&&d.values.length||1,h=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(d.disabled?" ui-slider-disabled ui-disabled":"")),this.range=a([]),d.range&&(d.range===!0&&(d.values||(d.values=[this._valueMin(),this._valueMin()]),d.values.length&&d.values.length!==2&&(d.values=[d.values[0],d.values[0]])),this.range=a("
    ").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(d.range==="min"||d.range==="max"?" ui-slider-range-"+d.range:"")));for(var i=e.length;ic&&(f=c,g=a(this),i=b)}),c.range===!0&&this.values(1)===c.min&&(i+=1,g=a(this.handles[i])),j=this._start(b,i);if(j===!1)return!1;this._mouseSliding=!0,h._handleIndex=i,g.addClass("ui-state-active").focus(),k=g.offset(),l=!a(b.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:b.pageX-k.left-g.width()/2,top:b.pageY-k.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(b,i,e),this._animateOff=!0;return!0},_mouseStart:function(a){return!0},_mouseDrag:function(a){var b={x:a.pageX,y:a.pageY},c=this._normValueFromMouse(b);this._slide(a,this._handleIndex,c);return!1},_mouseStop:function(a){this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(a,this._handleIndex),this._change(a,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1;return!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b,c,d,e,f;this.orientation==="horizontal"?(b=this.elementSize.width,c=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(b=this.elementSize.height,c=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),d=c/b,d>1&&(d=1),d<0&&(d=0),this.orientation==="vertical"&&(d=1-d),e=this._valueMax()-this._valueMin(),f=this._valueMin()+d*e;return this._trimAlignValue(f)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values());return this._trigger("start",a,c)},_slide:function(a,b,c){var d,e,f;this.options.values&&this.options.values.length?(d=this.values(b?0:1),this.options.values.length===2&&this.options.range===!0&&(b===0&&c>d||b===1&&c1)this.options.values[b]=this._trimAlignValue(c),this._refreshValue(),this._change(null,b);else{if(!arguments.length)return this._values();if(!a.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(b):this.value();d=this.options.values,e=arguments[0];for(f=0;f=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b,d=a-c;Math.abs(c)*2>=b&&(d+=c>0?b:-b);return parseFloat(d.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var b=this.options.range,c=this.options,d=this,e=this._animateOff?!1:c.animate,f,g={},h,i,j,k;this.options.values&&this.options.values.length?this.handles.each(function(b,i){f=(d.values(b)-d._valueMin())/(d._valueMax()-d._valueMin())*100,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",a(this).stop(1,1)[e?"animate":"css"](g,c.animate),d.options.range===!0&&(d.orientation==="horizontal"?(b===0&&d.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({width:f-h+"%"},{queue:!1,duration:c.animate})):(b===0&&d.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({height:f-h+"%"},{queue:!1,duration:c.animate}))),h=f}):(i=this.value(),j=this._valueMin(),k=this._valueMax(),f=k!==j?(i-j)/(k-j)*100:0,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",this.handle.stop(1,1)[e?"animate":"css"](g,c.animate),b==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},c.animate),b==="max"&&this.orientation==="horizontal"&&this.range[e?"animate":"css"]({width:100-f+"%"},{queue:!1,duration:c.animate}),b==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},c.animate),b==="max"&&this.orientation==="vertical"&&this.range[e?"animate":"css"]({height:100-f+"%"},{queue:!1,duration:c.animate}))}}),a.extend(a.ui.slider,{version:"1.8.18"})}(jQuery),function(a,b){function f(){return++d}function e(){return++c}var c=0,d=0;a.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:!1,cookie:null,collapsible:!1,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
    ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:"
  • #{label}
  • "},_create:function(){this._tabify(!0)},_setOption:function(a,b){if(a=="selected"){if(this.options.collapsible&&b==this.options.selected)return;this.select(b)}else this.options[a]=b,this._tabify()},_tabId:function(a){return a.title&&a.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+e()},_sanitizeSelector:function(a){return a.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+f());return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(a,b){return{tab:a,panel:b,index:this.anchors.index(a)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function m(b,c){b.css("display",""),!a.support.opacity&&c.opacity&&b[0].style.removeAttribute("filter")}var d=this,e=this.options,f=/^#.+/;this.list=this.element.find("ol,ul").eq(0),this.lis=a(" > li:has(a[href])",this.list),this.anchors=this.lis.map(function(){return a("a",this)[0]}),this.panels=a([]),this.anchors.each(function(b,c){var g=a(c).attr("href"),h=g.split("#")[0],i;h&&(h===location.toString().split("#")[0]||(i=a("base")[0])&&h===i.href)&&(g=c.hash,c.href=g);if(f.test(g))d.panels=d.panels.add(d.element.find(d._sanitizeSelector(g)));else if(g&&g!=="#"){a.data(c,"href.tabs",g),a.data(c,"load.tabs",g.replace(/#.*$/,""));var j=d._tabId(c);c.href="#"+j;var k=d.element.find("#"+j);k.length||(k=a(e.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(d.panels[b-1]||d.list),k.data("destroy.tabs",!0)),d.panels=d.panels.add(k)}else e.disabled.push(b)}),c?(this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"),this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.lis.addClass("ui-state-default ui-corner-top"),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom"),e.selected===b?(location.hash&&this.anchors.each(function(a,b){if(b.hash==location.hash){e.selected=a;return!1}}),typeof e.selected!="number"&&e.cookie&&(e.selected=parseInt(d._cookie(),10)),typeof e.selected!="number"&&this.lis.filter(".ui-tabs-selected").length&&(e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))),e.selected=e.selected||(this.lis.length?0:-1)):e.selected===null&&(e.selected=-1),e.selected=e.selected>=0&&this.anchors[e.selected]||e.selected<0?e.selected:0,e.disabled=a.unique(e.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(a,b){return d.lis.index(a)}))).sort(),a.inArray(e.selected,e.disabled)!=-1&&e.disabled.splice(a.inArray(e.selected,e.disabled),1),this.panels.addClass("ui-tabs-hide"),this.lis.removeClass("ui-tabs-selected ui-state-active"),e.selected>=0&&this.anchors.length&&(d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash)).removeClass("ui-tabs-hide"),this.lis.eq(e.selected).addClass("ui-tabs-selected ui-state-active"),d.element.queue("tabs",function(){d._trigger("show",null,d._ui(d.anchors[e.selected],d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash))[0]))}),this.load(e.selected)),a(window).bind("unload",function(){d.lis.add(d.anchors).unbind(".tabs"),d.lis=d.anchors=d.panels=null})):e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")),this.element[e.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible"),e.cookie&&this._cookie(e.selected,e.cookie);for(var g=0,h;h=this.lis[g];g++)a(h)[a.inArray(g,e.disabled)!=-1&&!a(h).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");e.cache===!1&&this.anchors.removeData("cache.tabs"),this.lis.add(this.anchors).unbind(".tabs");if(e.event!=="mouseover"){var i=function(a,b){b.is(":not(.ui-state-disabled)")&&b.addClass("ui-state-"+a)},j=function(a,b){b.removeClass("ui-state-"+a)};this.lis.bind("mouseover.tabs",function(){i("hover",a(this))}),this.lis.bind("mouseout.tabs",function(){j("hover",a(this))}),this.anchors.bind("focus.tabs",function(){i("focus",a(this).closest("li"))}),this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var k,l;e.fx&&(a.isArray(e.fx)?(k=e.fx[0],l=e.fx[1]):k=l=e.fx);var n=l?function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.hide().removeClass("ui-tabs-hide").animate(l,l.duration||"normal",function(){m(c,l),d._trigger("show",null,d._ui(b,c[0]))})}:function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.removeClass("ui-tabs-hide"),d._trigger("show",null,d._ui(b,c[0]))},o=k?function(a,b){b.animate(k,k.duration||"normal",function(){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),m(b,k),d.element.dequeue("tabs")})}:function(a,b,c){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),d.element.dequeue("tabs")};this.anchors.bind(e.event+".tabs",function(){var b=this,c=a(b).closest("li"),f=d.panels.filter(":not(.ui-tabs-hide)"),g=d.element.find(d._sanitizeSelector(b.hash));if(c.hasClass("ui-tabs-selected")&&!e.collapsible||c.hasClass("ui-state-disabled")||c.hasClass("ui-state-processing")||d.panels.filter(":animated").length||d._trigger("select",null,d._ui(this,g[0]))===!1){this.blur();return!1}e.selected=d.anchors.index(this),d.abort();if(e.collapsible){if(c.hasClass("ui-tabs-selected")){e.selected=-1,e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){o(b,f)}).dequeue("tabs"),this.blur();return!1}if(!f.length){e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){n(b,g)} +),d.load(d.anchors.index(this)),this.blur();return!1}}e.cookie&&d._cookie(e.selected,e.cookie);if(g.length)f.length&&d.element.queue("tabs",function(){o(b,f)}),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this));else throw"jQuery UI Tabs: Mismatching fragment identifier.";a.browser.msie&&this.blur()}),this.anchors.bind("click.tabs",function(){return!1})},_getIndex:function(a){typeof a=="string"&&(a=this.anchors.index(this.anchors.filter("[href$="+a+"]")));return a},destroy:function(){var b=this.options;this.abort(),this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs"),this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.anchors.each(function(){var b=a.data(this,"href.tabs");b&&(this.href=b);var c=a(this).unbind(".tabs");a.each(["href","load","cache"],function(a,b){c.removeData(b+".tabs")})}),this.lis.unbind(".tabs").add(this.panels).each(function(){a.data(this,"destroy.tabs")?a(this).remove():a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}),b.cookie&&this._cookie(null,b.cookie);return this},add:function(c,d,e){e===b&&(e=this.anchors.length);var f=this,g=this.options,h=a(g.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,d)),i=c.indexOf("#")?this._tabId(a("a",h)[0]):c.replace("#","");h.addClass("ui-state-default ui-corner-top").data("destroy.tabs",!0);var j=f.element.find("#"+i);j.length||(j=a(g.panelTemplate).attr("id",i).data("destroy.tabs",!0)),j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"),e>=this.lis.length?(h.appendTo(this.list),j.appendTo(this.list[0].parentNode)):(h.insertBefore(this.lis[e]),j.insertBefore(this.panels[e])),g.disabled=a.map(g.disabled,function(a,b){return a>=e?++a:a}),this._tabify(),this.anchors.length==1&&(g.selected=0,h.addClass("ui-tabs-selected ui-state-active"),j.removeClass("ui-tabs-hide"),this.element.queue("tabs",function(){f._trigger("show",null,f._ui(f.anchors[0],f.panels[0]))}),this.load(0)),this._trigger("add",null,this._ui(this.anchors[e],this.panels[e]));return this},remove:function(b){b=this._getIndex(b);var c=this.options,d=this.lis.eq(b).remove(),e=this.panels.eq(b).remove();d.hasClass("ui-tabs-selected")&&this.anchors.length>1&&this.select(b+(b+1=b?--a:a}),this._tabify(),this._trigger("remove",null,this._ui(d.find("a")[0],e[0]));return this},enable:function(b){b=this._getIndex(b);var c=this.options;if(a.inArray(b,c.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled"),c.disabled=a.grep(c.disabled,function(a,c){return a!=b}),this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(a){a=this._getIndex(a);var b=this,c=this.options;a!=c.selected&&(this.lis.eq(a).addClass("ui-state-disabled"),c.disabled.push(a),c.disabled.sort(),this._trigger("disable",null,this._ui(this.anchors[a],this.panels[a])));return this},select:function(a){a=this._getIndex(a);if(a==-1)if(this.options.collapsible&&this.options.selected!=-1)a=this.options.selected;else return this;this.anchors.eq(a).trigger(this.options.event+".tabs");return this},load:function(b){b=this._getIndex(b);var c=this,d=this.options,e=this.anchors.eq(b)[0],f=a.data(e,"load.tabs");this.abort();if(!f||this.element.queue("tabs").length!==0&&a.data(e,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(d.spinner){var g=a("span",e);g.data("label.tabs",g.html()).html(d.spinner)}this.xhr=a.ajax(a.extend({},d.ajaxOptions,{url:f,success:function(f,g){c.element.find(c._sanitizeSelector(e.hash)).html(f),c._cleanup(),d.cache&&a.data(e,"cache.tabs",!0),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.success(f,g)}catch(h){}},error:function(a,f,g){c._cleanup(),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.error(a,f,b,e)}catch(g){}}})),c.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]),this.panels.stop(!1,!0),this.element.queue("tabs",this.element.queue("tabs").splice(-2,2)),this.xhr&&(this.xhr.abort(),delete this.xhr),this._cleanup();return this},url:function(a,b){this.anchors.eq(a).removeData("cache.tabs").data("load.tabs",b);return this},length:function(){return this.anchors.length}}),a.extend(a.ui.tabs,{version:"1.8.18"}),a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(a,b){var c=this,d=this.options,e=c._rotate||(c._rotate=function(b){clearTimeout(c.rotation),c.rotation=setTimeout(function(){var a=d.selected;c.select(++a