Merge pull request #164 from ahgittin/quick-launch-auto-name

auto-set a name for the app in quick-launch, and
diff --git a/ui-modules/home/app/views/main/deploy/deploy.controller.js b/ui-modules/home/app/views/main/deploy/deploy.controller.js
index 896ec7e..cab9db2 100644
--- a/ui-modules/home/app/views/main/deploy/deploy.controller.js
+++ b/ui-modules/home/app/views/main/deploy/deploy.controller.js
@@ -22,6 +22,7 @@
 import brooklynApi from 'brooklyn-ui-utils/brooklyn.api/brooklyn.api';
 import {HIDE_INTERSTITIAL_SPINNER_EVENT} from 'brooklyn-ui-utils/interstitial-spinner/interstitial-spinner';
 import modalTemplate from './modal.template.html';
+import {filterCatalogQuickLaunch} from '../main.controller.js';  // this really should be handled by angular DI 
 
 const MODULE_NAME = 'states.main.deploy';
 
@@ -54,9 +55,7 @@
             entitySpec: ['catalogApi', (catalogApi) => {
                 return catalogApi.getBundleType($stateParams.bundleSymbolicName, $stateParams.bundleVersion, $stateParams.typeSymbolicName, $stateParams.typeVersion);
             }],
-            locations: ['locationApi', (locationApi) => {
-                return locationApi.getLocations();
-            }]
+            locations: ['locationApi', locationApi => locationApi.getLocations()],
         }
     });
 
@@ -80,9 +79,20 @@
 
     function modalController($scope, $location, entitySpec, locations) {
         $scope.app = entitySpec;
-        $scope.locations = locations;
-        // can optionally add: { noEditButton: true, noComposerButton: true }, or pass in URL
-        $scope.args = angular.extend({}, $location.search());
+        $scope.locations = filterCatalogQuickLaunch(locations, (t) => {
+                $scope.usingLocationCatalogQuickLaunchTags = t.length > 0;
+            });
+        
+        // also supports { noEditButton: true, noComposerButton: true }
+        // see quick-launch.js for more info
+        $scope.args = angular.extend({
+                // disable "create location" is admin has configured locations with tags.
+                // called out in docs in https://github.com/apache/brooklyn-docs/pull/299.
+                // a better approach would be to add config on the server to configure this.
+                noCreateLocationLink: $scope.usingLocationCatalogQuickLaunchTags
+            },
+            $location.search());
+        
     }
 }
 
diff --git a/ui-modules/home/app/views/main/main.controller.js b/ui-modules/home/app/views/main/main.controller.js
index e967953..a3bdff1 100644
--- a/ui-modules/home/app/views/main/main.controller.js
+++ b/ui-modules/home/app/views/main/main.controller.js
@@ -41,20 +41,30 @@
             return brooklynUiModulesApi.getUiModules();
         }],
         catalogApps: ['catalogApi', (catalogApi) => {
-            return catalogApi.getTypes({params: {supertype: 'org.apache.brooklyn.api.entity.Application'}}).then(applications => {
-                // optionally tag things with 'catalog_quick_launch': if any apps are so tagged, 
-                // then only apps with such tags will be shown;
-                // in all cases only show those marked as templates
-                var appsWithTag = applications.filter(application => application.tags && application.tags.indexOf("catalog_quick_launch")>=0);
-                if (appsWithTag.length) {
-                    applications = appsWithTag;
-                }
-                return applications.filter(application => application.template);
-            });
+            return catalogApi.getTypes({params: {supertype: 'org.apache.brooklyn.api.entity.Application'}}).then(
+                applications => filterCatalogQuickLaunch(applications.filter(application => application.template))
+            );
         }]
     }
 };
 
+export function filterCatalogQuickLaunch(list, callbackForFiltered) {
+    // optionally tag things with 'catalog_quick_launch': if any apps are so tagged, 
+    // then only apps with such tags will be shown; otherwise show all marked as templates.
+    
+    // the callback is used for clients who wish to adjust their behaviour if tags are used,
+    // eg in deploy.controller where noCreateLocationLink is set on the quick launch if there are tagged locations
+    
+    if (!list) { 
+        list = [];
+    }
+    let tagged = list.filter(i => i && i.tags && i.tags.indexOf("catalog_quick_launch")>=0);
+    if (callbackForFiltered) {
+        callbackForFiltered(tagged, list);
+    }
+    return tagged.length ? tagged : list;
+}
+
 export function mainStateConfig($stateProvider) {
     $stateProvider.state(mainState);
 }
diff --git a/ui-modules/utils/quick-launch/quick-launch.html b/ui-modules/utils/quick-launch/quick-launch.html
index 99f4d5e..a2a6a4c 100644
--- a/ui-modules/utils/quick-launch/quick-launch.html
+++ b/ui-modules/utils/quick-launch/quick-launch.html
@@ -39,7 +39,8 @@
             <h3 class="quick-launch-section-title">Name</h3>
             <div class="quick-launch-section-content">
                 <div class="form-group">
-                    <input class="form-control" type="text" ng-model="model.name" ng-disabled="deploying" name="name" placeholder="Choose a name for this application (Optional)" autofocus />
+                    <input class="form-control" type="text" ng-model="model.name" ng-disabled="deploying" name="name" 
+                        placeholder="{{ 'Choose a name for this application (Optional)' }}" />
                 </div>
             </div>
         </section>
@@ -55,7 +56,7 @@
                            required />
                     <small class="help-block">
                         <span ng-if="deploy.location.$error.required && (deploy.$submitted || deploy.location.$touched)">You must select a location.</span>
-                        <span>Alternatively, you can <a href="/brooklyn-ui-location-manager/#!/wizard">create a new location</a></span>
+                        <span ng-if="!args.noCreateLocationLink">Alternatively, you can <a href="/brooklyn-ui-location-manager/#!/wizard">create a new location</a></span>
                     </small>
                 </div>
             </div>
diff --git a/ui-modules/utils/quick-launch/quick-launch.js b/ui-modules/utils/quick-launch/quick-launch.js
index 40ff963..a114aae 100644
--- a/ui-modules/utils/quick-launch/quick-launch.js
+++ b/ui-modules/utils/quick-launch/quick-launch.js
@@ -38,7 +38,7 @@
         scope: {
             app: '=',
             locations: '=',
-            args: '=?',
+            args: '=?', // default behaviour of code is: { noEditButton: false, noComposerButton: false, noCreateLocationLink: false, location: null }
             callback: '=?',
         },
         controller: ['$scope', '$http', '$location', 'brSnackbar', controller]
@@ -47,11 +47,21 @@
     function controller($scope, $http, $location, brSnackbar) {
         $scope.deploying = false;
         $scope.model = {
-            newConfigFormOpen: false
+            newConfigFormOpen: false,
+            
+            // should never be null, so the placeholder in UI for model.name will never be used;
+            // hence autofocus is disabled
+            name: ($scope.app && ($scope.app.name || $scope.app.symbolicName)) || null, 
         };
         $scope.args = $scope.args || {};
         if ($scope.args.location) {
             $scope.model.location = $scope.args.location;
+        } else {
+            if ($scope.locations) {
+                if ($scope.locations.length == 1) {
+                    $scope.model.location = $scope.locations[0];
+                }
+            } 
         }
         $scope.toggleNewConfigForm = toggleNewConfigForm;
         $scope.addNewConfigKey = addNewConfigKey;