
<!--
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.
-->

<!-- Help page -->
<div class="container container-fluid single-main-container brooklyn-help-page">
<div id="help-page">
    <div class="help-logo-right"><img width="450" src="./assets/img/bridge.png"/></div>
    <h3>Brooklyn Help</h3>
    
    <p>This is the Brooklyn JavaScript web client for the REST API.<br/>
    Brooklyn is an Apache-licensed open-source project for deployment and management.
    </p>
    
    <p>You are currently using Brooklyn Version 0.11.0-SNAPSHOT.</p> <!-- BROOKLYN_VERSION -->
    
    <hr/>
    Some useful references include:
    <ul>
        <li><a href="http://brooklyn.io">Brooklyn Project web page</a></li>
        <li><a href="http://github.com/brooklyncentral/brooklyn">Code at Github</a></li>
    </ul>
    <p>
    Note you can observe the REST requests made by the Javascript GUI 
    through the developers console in many browsers.
    <hr/>
    Some miscellaneous Brooklyn control options are:
    <ul>
        <li><a href="/logout">Log out</a></li>
        <li>Shutdown Brooklyn Server: <a href="javascript:postShutdown(true)">stop all apps</a> or <a href="javascript:postShutdown(false)">leave apps running</a></li>
        <script type="text/javascript">
        function postShutdown(stopAppsFirst) {
          if (window.confirm("Really shutdown the Brooklyn server?")) {
            $.ajax({
                type:"POST",
                url:"/v1/server/shutdown",
                data: { stopAppsFirst: stopAppsFirst, shutdownTimeout: 0, requestTimeout: 0 },
                success:function (data) {
                    // unfaded if server restarted, in router.js ServerCautionOverlay
                    $('#application-content').fadeTo(500,0.1);
                },
                error: function(data) {
                    $('#application-content')
                        .fadeTo(200,0.2)
                        .delay(200).fadeTo(200,1)
                        .delay(200).fadeTo(100,0.2)
                        .delay(200).fadeTo(200,1)
//                      .delay(200).fadeTo(100,0.2)
//                      .delay(200).fadeTo(200,1)
                    // TODO render the error better than poor-man's flashing
                    
                    console.error("ERROR shutting down")
                    console.debug(data)
                }})
          }
        }
        </script>
    </ul> 
    (These are living here until a more appropriate home for them is built.)
</div>
</div>
