This closes #108
diff --git a/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js b/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js
index be05fff..252f6da 100644
--- a/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js
+++ b/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.directive.js
@@ -44,6 +44,7 @@
angular.module(MODULE_NAME, [angularAnimate, uibModal, brUtils])
.directive('catalogSaver', ['$rootScope', '$uibModal', '$injector', 'composerOverrides', 'blueprintService', saveToCatalogModalDirective])
.directive('catalogVersion', ['$parse', catalogVersionDirective])
+ .filter('bundlize', bundlizeProvider)
.run(['$templateCache', templateCache]);
export default MODULE_NAME;
@@ -87,10 +88,9 @@
$scope.config.symbolicName = entity.id || metadata.get('id');
}
if (!$scope.config.bundle) {
- let bundle = $scope.config.symbolicName || $scope.config.name || 'untitled';
- $scope.config.bundle = bundle.split(/[^-a-zA-Z0-9._]+/).join('-').toLowerCase();
- if (!$scope.config.symbolicName) {
- $scope.config.symbolicName = $scope.config.bundle;
+ // NB: when editing a bundle this will already be set
+ if ($scope.config.symbolicName) {
+ $scope.config.bundle = $scope.config.symbolicName;
}
}
@@ -100,7 +100,7 @@
let modalInstance = $uibModal.open({
templateUrl: TEMPLATE_MODAL_URL,
size: 'save',
- controller: ['$scope', 'blueprintService', 'paletteApi', 'brUtilsGeneral', CatalogItemModalController],
+ controller: ['$scope', '$filter', 'blueprintService', 'paletteApi', 'brUtilsGeneral', CatalogItemModalController],
scope: $scope,
});
@@ -119,7 +119,7 @@
}
}
-export function CatalogItemModalController($scope, blueprintService, paletteApi, brUtilsGeneral) {
+export function CatalogItemModalController($scope, $filter, blueprintService, paletteApi, brUtilsGeneral) {
$scope.REASONS = REASONS;
$scope.VIEWS = VIEWS;
$scope.TYPES = TYPES;
@@ -133,9 +133,9 @@
$scope.getTitle = () => {
switch ($scope.state.view) {
case VIEWS.form:
- return $scope.isUpdate ? `Update ${$scope.config.name || $scope.config.symbolicName}` : 'Add to catalog';
+ return $scope.isUpdate ? `Update ${$scope.config.name || $scope.config.symbolicName || 'blueprint'}` : 'Add to catalog';
case VIEWS.saved:
- return `${$scope.config.name || $scope.config.symbolicName} ${$scope.isUpdate ? 'updated' : 'saved'}`;
+ return `${$scope.config.name || $scope.config.symbolicName || 'Blueprint'} ${$scope.isUpdate ? 'updated' : 'saved'}`;
}
};
@@ -160,11 +160,22 @@
function createBom() {
let blueprint = blueprintService.getAsJson();
+ let bundleBase = $scope.config.bundle || $filter('bundlize')($scope.config.name);
+ let bundleId = $scope.config.symbolicName || $filter('bundlize')($scope.config.name);
+ if (!bundleBase || !bundleId) {
+ throw "Either display name must be set of bundle and symbolic name explicitly set";
+ }
+
let bomItem = {
- id: $scope.config.symbolicName,
+ id: bundleId,
itemType: $scope.config.itemType,
item: blueprint
};
+ let bomCatalogYaml = {
+ bundle: `catalog-bom-${bundleBase}`,
+ version: $scope.config.version,
+ items: [ bomItem ]
+ };
if (brUtilsGeneral.isNonEmpty($scope.config.name)) {
bomItem.name = $scope.config.name;
}
@@ -174,14 +185,8 @@
if (brUtilsGeneral.isNonEmpty($scope.config.iconUrl)) {
bomItem.iconUrl = $scope.config.iconUrl;
}
-
- return jsYaml.dump({
- 'brooklyn.catalog': {
- bundle: `catalog-bom-${$scope.config.bundle}`,
- version: $scope.config.version,
- items: [bomItem]
- }
- });
+
+ return jsYaml.dump({ 'brooklyn.catalog': bomCatalogYaml });
}
}
@@ -223,3 +228,7 @@
$templateCache.put(TEMPLATE_URL, template);
$templateCache.put(TEMPLATE_MODAL_URL, modalTemplate);
}
+
+function bundlizeProvider() {
+ return (input) => input && input.split(/[^a-zA-Z0-9]+/).filter(x => x).join('-').toLowerCase();
+}
diff --git a/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.modal.template.html b/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.modal.template.html
index 6690456..c3a6cb7 100644
--- a/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.modal.template.html
+++ b/ui-modules/blueprint-composer/app/components/catalog-saver/catalog-saver.modal.template.html
@@ -24,9 +24,12 @@
<div class="modal-body add-to-catalog-modal">
<form ng-show="state.view === VIEWS.form" name="form" novalidate>
- <div class="form-group">
+ <div class="form-group" ng-class="{'has-error': form.name.$invalid}">
<label class="control-label">Blueprint display name</label>
- <input ng-model="config.name" ng-disabled="state.saving" class="form-control" name="name" type="text" />
+ <input ng-model="config.name" ng-disabled="state.saving" class="form-control" name="name" type="text" required />
+ <p class="help-block" ng-show="form.name.$invalid">
+ <span ng-if="form.name.$error.required">You must specify a name for this item</span>
+ </p>
</div>
<div class="form-group">
@@ -57,19 +60,17 @@
<label class="control-label">Bundle ID</label>
<div class="input-group">
<span class="input-group-addon">catalog-bom-</span>
- <input ng-model="config.bundle" ng-disabled="state.saving" class="form-control" placeholder="E.g my-bundle" name="bundle" required ng-pattern="state.pattern" autofocus />
+ <input ng-model="config.bundle" ng-disabled="state.saving" class="form-control" name="bundle" ng-pattern="state.pattern" autofocus placeholder="{{ (config.name | bundlize) || 'E.g. my-bundle-id' }}"/>
</div>
<p class="help-block" ng-show="form.bundle.$invalid">
- <span ng-if="form.bundle.$error.required">You must specify a bundle ID</span>
<span ng-if="form.bundle.$error.pattern">The bundle ID can contains only letters, numbers as well a the following characters: <code>.</code>, <code>-</code> and <code>_</code></span>
</p>
</div>
<div class="form-group" ng-class="{'has-error': form.symbolicName.$invalid}">
<label class="control-label">Blueprint symbolic name</label>
- <input ng-model="config.symbolicName" ng-disabled="state.saving" class="form-control" placeholder="E.g my-catalog-id" name="symbolicName" required ng-pattern="state.pattern" autofocus />
+ <input ng-model="config.symbolicName" ng-disabled="state.saving" class="form-control" name="symbolicName" ng-pattern="state.pattern" autofocus placeholder="{{ (config.name | bundlize) || 'E.g. my-catalog-id' }}"/>
<p class="help-block" ng-show="form.symbolicName.$invalid">
- <span ng-if="form.symbolicName.$error.required">You must specify a blueprint symbolic name</span>
<span ng-if="form.symbolicName.$error.pattern">The blueprint symbolic name can contains only letters, numbers as well a the following characters: <code>.</code>, <code>-</code> and <code>_</code></span>
</p>
</div>