From 4d18a46ee3ada751517f9bf767d5057a3bf5eb9e Mon Sep 17 00:00:00 2001
From: rsanchez <rsanchez@curisit.net>
Date: Thu, 16 Oct 2014 18:16:33 +0000
Subject: [PATCH] #2021 feature - Added Pack management (in Beta) 

---
 securis/src/main/resources/static/admin.html           |    2 
 securis/src/main/resources/static/licenses.html        |  139 +++++++++++++++++++++------
 securis/src/main/resources/static/js/licenses.js       |   63 +++++++++++-
 securis/src/main/resources/static/js/login.js          |   10 +
 securis/src/main/resources/static/js/admin.js          |    6 
 securis/src/main/resources/static/js/main.js           |   12 +
 securis/src/main/java/net/curisit/securis/db/Pack.java |   36 +++++++
 securis/src/main/resources/db/schema.sql               |    3 
 8 files changed, 221 insertions(+), 50 deletions(-)

diff --git a/securis/src/main/java/net/curisit/securis/db/Pack.java b/securis/src/main/java/net/curisit/securis/db/Pack.java
index 6e89e47..c6f3274 100644
--- a/securis/src/main/java/net/curisit/securis/db/Pack.java
+++ b/securis/src/main/java/net/curisit/securis/db/Pack.java
@@ -73,6 +73,16 @@
     @Column(name = "num_licenses")
     @JsonProperty("num_licenses")
     private int numLicenses;
+    
+    @Column(name = "init_valid_date")
+    @JsonProperty("init_valid_date")
+    private Date initValidDate;
+
+    @Column(name = "end_valid_date")
+    @JsonProperty("end_valid_date")
+    private Date endValidDate;
+
+    private String status;
 
     @Column(name = "license_preactivation")
     @JsonProperty("license_preactivation")
@@ -239,7 +249,7 @@
 
     @JsonProperty("created_by_name")
     public String getCreatedByname() {
-        return createdBy == null ? null : String.format("%s %s (%s)", createdBy.getFirstName(), createdBy.getLastName(), createdBy.getUsername());
+        return createdBy == null ? null : String.format("%s %s (%s)", createdBy.getFirstName(), createdBy.getLastName() != null ? createdBy.getLastName() : "", createdBy.getUsername());
     }
 
     @JsonProperty("licensetype_code")
@@ -271,6 +281,30 @@
         this.metadata = metadata;
     }
 
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public Date getInitValidDate() {
+        return initValidDate;
+    }
+
+    public void setInitValidDate(Date initValidDate) {
+        this.initValidDate = initValidDate;
+    }
+
+    public Date getEndValidDate() {
+        return endValidDate;
+    }
+
+    public void setEndValidDate(Date endValidDate) {
+        this.endValidDate = endValidDate;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (!(obj instanceof Pack))
diff --git a/securis/src/main/resources/db/schema.sql b/securis/src/main/resources/db/schema.sql
index b6337b0..b249a28 100644
--- a/securis/src/main/resources/db/schema.sql
+++ b/securis/src/main/resources/db/schema.sql
@@ -75,6 +75,9 @@
   id INT NOT NULL auto_increment,
   code VARCHAR(50) NOT NULL ,
   num_licenses INT NOT NULL ,
+  init_valid_date DATE NOT NULL default today(),
+  end_valid_date DATE NOT NULL default today(),
+  status VARCHAR(2) NOT NULL default 'PE',
   comments VARCHAR(1024) NULL ,
   license_type_id INT NOT NULL,  
   organization_id INT NOT NULL,  
diff --git a/securis/src/main/resources/static/admin.html b/securis/src/main/resources/static/admin.html
index 789ecde..8ef388b 100644
--- a/securis/src/main/resources/static/admin.html
+++ b/securis/src/main/resources/static/admin.html
@@ -77,7 +77,7 @@
 											  </td>
 											  <td>
 												<input type="text" id="md_value" name="md_value" placeholder=""
-													class="form-control" ng-model="row_md['value']" ng-required="row_md['mandatory']" ng-maxlength="150" />
+													class="form-control" ng-model="row_md['value']" ng-required="false" ng-maxlength="150" />
 											  </td>
 											  <td>
 												<input type="checkbox" id="md_mandatory" name="md_mandatory" ng-disabled="!field.allow_creation"
diff --git a/securis/src/main/resources/static/js/admin.js b/securis/src/main/resources/static/js/admin.js
index d3f015b..566f992 100644
--- a/securis/src/main/resources/static/js/admin.js
+++ b/securis/src/main/resources/static/js/admin.js
@@ -38,7 +38,9 @@
 			'$store',
 			'$L',
 			function($scope, $http, toaster, Catalogs, $store, $L) {
-				$scope.showForm = false;
+                $store.set('location', '/admin');
+
+                $scope.showForm = false;
 				$scope.isNew = false;
 				$scope.formu = {};
 				$scope.catalogIndex = 0;
@@ -145,8 +147,6 @@
 					$('select').val(null);
 					$scope.$parent.formu = {};
 					
-					console.log("Refs for new form:");
-					console.log($scope.refs);
 					var fields = Catalogs.getMetadata().fields;
 					fields.forEach(function(field) {
 						if (!field.listingOnly) $scope.$parent.formu[field.name] = null;
diff --git a/securis/src/main/resources/static/js/licenses.js b/securis/src/main/resources/static/js/licenses.js
index 15a7306..a2e3a20 100644
--- a/securis/src/main/resources/static/js/licenses.js
+++ b/securis/src/main/resources/static/js/licenses.js
@@ -74,7 +74,8 @@
 	                    			'$store',
 	                    			'$L',
 	   			function($scope, $http, toaster, $store, $L) {
-	                    					
+	                    $store.set('location', '/licenses');
+	                    				
         				$scope.maxLengthErrorMsg = function(displayname, fieldMaxlength) {
         					return $L.get("{0} length is too long (max: {1}).", $L.get(displayname), fieldMaxlength);
         				}
@@ -101,6 +102,13 @@
 				var packResource = $resource('/pack/:packId', {
 					packId : '@id'
 				});
+				var PACK_STATUS = [
+				                   {id: 'PE', label: $L.get('Pending')},
+				                   {id: 'AC', label: $L.get('Active')},
+				                   {id: 'OH', label: $L.get('On Hold')},
+				                   {id: 'EX', label: $L.get('Expired')},
+				                   {id: 'CA', label: $L.get('Cancelled')}
+				                   ];
 				$scope.mandatory = {
 						code: true,
 						num_licenses: true,
@@ -116,6 +124,7 @@
                 	var refFields = [{resource: 'organization', name: 'organization_id'},{resource: 'licensetype', name: 'license_type_id'}]; 
                     Catalogs.loadRefs(function(refs) {
 	                    	$scope.refs = refs;
+	                    	$scope.refs['pack_status'] = PACK_STATUS;
 	                    }, refFields);
                 }); 
 
@@ -128,12 +137,28 @@
 
 				$scope.packs = packResource.query();
 				
-				$scope.save = function() {
+				var _savePackData = function() {
 					var _success = function() {
 					    if (!$scope.isNew) $scope.showForm = false;
 						$scope.packs = packResource.query();
+						toaster.pop('success', Catalogs.getName(), $L.get("Pack '{0}' {1} successfully", $scope.pack.code, $scope.isNew ? $L.get("created") : $L.get("updated")));
 					}
-					packResource.save($scope.pack, _success)
+					var _error =  function(error) {
+                        console.log(error);
+						toaster.pop('error', Catalogs.getName(), $L.get("Error {0} pack '{1}'. Reason: {2}", $scope.isNew ? $L.get("creating") : $L.get("updating"), $scope.pack.code, $L.get(error.headers('X-SECURIS-ERROR'))));
+					}
+					packResource.save($scope.pack, _success, _error);
+				} 
+				$scope.save = function() {
+					if ($scope.pack.num_activations > 0) {
+						BootstrapDialog.confirm($L.get("The pack '{0}' has active licenses, Do you want to modify it ?", $scope.pack.code), function(answer){
+	                        if (answer) {
+	                        	_savePackData();
+	                        }
+	                    });
+					} else {
+				    	_savePackData();
+				    }
 				}
 				
 				$scope.newPack = function() {
@@ -141,9 +166,10 @@
 					$scope.showForm = true;
 					$scope.pack = {
                             license_preactivation: true,
+                            status: 'PE',
                             num_licenses: 1,
-                            license_type_id: !$scope.refs.license_type_id || !$scope.refs.license_type_id.length ? null : $scope.refs.license_type_id[0].id,
-                            organization_id: !$scope.refs.organization_id || !$scope.refs.organization_id.length ? null : $scope.refs.organization_id[0].id
+                            license_type_id: null,
+                            organization_id: null  //!$scope.refs.organization_id || !$scope.refs.organization_id.length ? null : $scope.refs.organization_id[0].id
 					}
                    setTimeout(function() {
                         $('#code').focus();
@@ -188,6 +214,33 @@
 					$scope.$parent.$broadcast('pack_changed', pack);
 				}
 				
+				$scope.createMetadataRow = function() {
+					if (!$scope.formu.metadata) {
+						$scope.formu.metadata = [];
+					}
+					$scope.formu.metadata.push({key: '', value: '', mandatory: true});
+				}
+				$scope.removeMetadataKey = function(row_md) {
+					$scope.formu.metadata.splice( $scope.formu.metadata.indexOf(row_md), 1 );
+				}
+				$scope.updateMetadata = function() {
+					// Called when Application ID change in current field
+					var newLTId = $scope.pack['license_type_id'];
+					if (newLTId) {
+						// Only if there is a "valid" value selected we should update the metadata
+						Catalogs.getResource('licensetype').get({licenseTypeId: newLTId}).$promise.then(function(lt) {
+							$scope.pack.metadata = [];
+							lt.metadata.forEach(function(md) {
+								$scope.pack.metadata.push({
+									key: md.key,
+									value: md.value,
+									readonly: !!md.value,
+									mandatory: md.mandatory
+								});
+							});
+						});
+					}
+				}
 			} ]);
 
 	   app.controller('LicensesCtrl', [
diff --git a/securis/src/main/resources/static/js/login.js b/securis/src/main/resources/static/js/login.js
index 704bdc3..8051120 100644
--- a/securis/src/main/resources/static/js/login.js
+++ b/securis/src/main/resources/static/js/login.js
@@ -23,14 +23,18 @@
 			}).
 			  success(function(data, status, headers, config) {
 				  toaster.pop('success', $L.get('Login successful'), $L.get('User {0} has logged in application', $scope.username), 1500);
-				  $location.path('/licenses');
+				  var location = $store.get('location') || '/licenses';
+
+				  $location.path(location);
 				  $store.put('username', $scope.username);
 				  $store.put('token', data.token);
 				  $http.defaults.headers.common['X-SECURIS-TOKEN'] = data.token; 
 			  }).
 			  error(function(data, status, headers, config) {
-				if (status === 403 /* forbidden */) {
-					toaster.pop('error', $L.get('Login error'), $L.get('Invalid credentials'), 3000);
+				if (status === 403 /* forbidden */ || status === 401 /* unauthorized */) {
+					toaster.pop('error', $L.get('Login error'), $L.get('Invalid credentials'), 2000);
+				} else if (status === 418 /* Teapot */) {
+					toaster.pop('error', $L.get('Login error'), $L.get(headers['X-SECURIS-ERROR-MSG']), 2000);
 				} else {
 					console.error(data + " status: "+ status);
 					toaster.pop('error', $L.get('Unexpected Login error'), $L.get('Unexpected error HTTP ({0}) accessing to server. Contact with the administrator.', status), 5000);
diff --git a/securis/src/main/resources/static/js/main.js b/securis/src/main/resources/static/js/main.js
index 1406d54..1c7c442 100644
--- a/securis/src/main/resources/static/js/main.js
+++ b/securis/src/main/resources/static/js/main.js
@@ -78,10 +78,14 @@
 		    // configure html5 to get links working on jsfiddle
 		    $locationProvider.html5Mode(true);
 		    $httpProvider.interceptors.push('securisHttpInterceptor');
-		});	
+		});
+	
 	m.controller('MainCtrl', ['$scope', '$http', '$location', '$L', '$store',
 	                             function($scope, $http, $location, $L, $store) {
 		
+		$scope.currentRoute = null;
+		console.log('Current location: ' + $location);
+		console.log($location);
 		$location.path('/login');
 		if ($store.get('token') != null) {
 			
@@ -91,8 +95,10 @@
 				}
 			}).success(function(data) {
 				if (data.valid) {
-					$http.defaults.headers.common['X-SECURIS-TOKEN'] = $store.get('token'); 
-					$location.path('/licenses');
+					$http.defaults.headers.common['X-SECURIS-TOKEN'] = $store.get('token');
+					var location = $store.get('location') || '/licenses';
+
+				    $location.path(location);
 					$store.set('user', data.user);
 				}
 			});
diff --git a/securis/src/main/resources/static/licenses.html b/securis/src/main/resources/static/licenses.html
index 9f290c9..7d40fa9 100644
--- a/securis/src/main/resources/static/licenses.html
+++ b/securis/src/main/resources/static/licenses.html
@@ -21,15 +21,16 @@
 						</a></li>
 					</ul>
 					<div class="navbar-form navbar-right form-group">
-					<span class="input-group input-group-sm">
-							<div class="input-group-addon" style="width: 28px;" >
+						<span class="input-group input-group-sm">
+							<div class="input-group-addon" style="width: 28px;">
 								<span class=" glyphicon glyphicon-search"></span>
+							</div> <input type="text" class="form-control" placeholder="Search"
+							ng-model="$searchPacksText">
+							<div class="input-group-addon" style="width: 20px;">
+								<span class=" glyphicon glyphicon-remove"
+									ng-click="$searchPacksText = '';"></span>
 							</div>
-							<input type="text" class="form-control" placeholder="Search" ng-model="$searchPacksText">
-							<div class="input-group-addon" style="width: 20px;" >
-								<span class=" glyphicon glyphicon-remove" ng-click="$searchPacksText = '';"></span>
-							</div>
-					</span>
+						</span>
 					</div>
 				</div>
 			</div>
@@ -63,6 +64,32 @@
 				</div>
 
 				<div class="form-group">
+					<label class="col-md-3 control-label" for="code" i18n>Validity (from - to)</label>
+					<div class="col-md-4">
+						<input type="date" id="init_valid_date" name="init_valid_date" placeholder=""
+							class="form-control" ng-model="pack.init_valid_date"
+							ng-required="mandatory.init_valid_date"  />
+						<div class="alert inline-alert alert-warning"
+							ng-show="packForm.initValidDate.$invalid">
+							<span class="glyphicon glyphicon-warning-sign"></span> 
+							<span ng-show="packForm.init_valid_date.$error.required"
+								ng-bind="mandatoryFieldErrorMsg('Init valid date')"></span>
+						</div>
+					</div>
+					<div class="col-md-4">
+						<input type="date" id="end_valid_date" name="end_valid_date" placeholder=""
+							class="form-control" ng-model="pack.end_valid_date"
+							ng-required="mandatory.end_valid_date"  />
+						<div class="alert inline-alert alert-warning"
+							ng-show="packForm.initValidDate.$invalid">
+							<span class="glyphicon glyphicon-warning-sign"></span> 
+							<span ng-show="packForm.end_valid_date.$error.required"
+								ng-bind="mandatoryFieldErrorMsg('End valid date')"></span>
+						</div>
+					</div>
+				</div>
+
+				<div class="form-group">
 					<label class="col-md-3 control-label" for="num_licenses" i18n>Num.
 						Licenses</label>
 					<div class="col-md-8">
@@ -80,15 +107,33 @@
 					</div>
 				</div>
 
+				<div class="form-group" ng-if="!isNew">
+					<label class="col-md-3 control-label" for="status" i18n>Status</label>
+					<div class="col-md-8">
+						<select class="form-control" id="status"
+							ng-required="mandatory.status"
+							ng-model="pack.status"
+							ng-options="o.id as o.label for o in refs.pack_status">
+						</select>
+						<div class="alert inline-alert alert-warning"
+							ng-show="packForm.status.$invalid">
+							<span class="glyphicon glyphicon-warning-sign"></span> <span
+								ng-show="packForm.status.$error.required"
+								ng-bind="mandatoryFieldErrorMsg('Status')"></span>
+						</div>
+					</div>
+				</div>
+
 				<div class="form-group">
 					<label class="col-md-3 control-label" for="license_type_id" i18n>License
 						type</label>
 					<div class="col-md-8">
-						<select class="form-control"
+						<select class="form-control" id="license_type_id"
+						    ng-change="updateMetadata()"
 							ng-required="mandatory.license_type_id"
 							ng-model="pack.license_type_id"
 							ng-options="o.id as o.label for o in refs.license_type_id">
-							
+
 						</select>
 						<div class="alert inline-alert alert-warning"
 							ng-show="packForm.license_type_id.$invalid">
@@ -143,17 +188,42 @@
 				</div>
 
 				<div class="form-group" ng-if="!isNew">
-					<label class="col-md-3 control-label">Created by</label>
+					<label i18n class="col-md-3 control-label">Created by</label>
 					<div class="col-md-8">
 						<p class="form-control-static" ng-bind="pack.created_by_name"></p>
 					</div>
 				</div>
 
 				<div class="form-group" ng-if="!isNew">
-					<label class="col-md-3 control-label">Creation date</label>
+					<label i18n class="col-md-3 control-label">Creation date</label>
 					<div class="col-md-8">
 						<p class="form-control-static"
 							ng-bind="pack.creationTimestamp | date:'medium'"></p>
+					</div>
+				</div>
+
+				<div class="form-group">
+					<label class="col-md-3 control-label" i18n>Metadata</label>
+					<div class="col-md-8">
+						<table class="table table-hover table-condensed">
+							<thead>
+								<tr>
+									<th i18n>Key</th>
+									<th i18n>Value</th>
+								</tr>
+							</thead>
+							<tbody>
+								<tr ng-repeat="row_md in pack.metadata">
+									<td><input type="text" id="md_key" name="md_key"
+										placeholder="" ng-readonly="true"
+										class="form-control" ng-model="row_md['key']"
+										ng-required="true" /></td>
+									<td><input type="text" id="md_value" name="md_value" ng-readonly="row_md['readonly']"
+										placeholder="" class="form-control" ng-model="row_md['value']"
+										ng-required="row_md['mandatory']" ng-maxlength="150" /></td>
+								</tr>
+							</tbody>
+						</table>
 					</div>
 				</div>
 
@@ -213,33 +283,34 @@
 		<nav class="navbar navbar-default navbar-static-top"
 			ng-disabled="!currentPack">
 			<div class="container-fluid">
-			<!-- Brand and toggle get grouped for better mobile display -->
-			<div class="navbar-header success">
-				<a class="navbar-brand" i18n>Licenses</a>
-			</div>
+				<!-- Brand and toggle get grouped for better mobile display -->
+				<div class="navbar-header success">
+					<a class="navbar-brand" i18n>Licenses</a>
+				</div>
 
-			<!-- Collect the nav links, forms, and other content for toggling -->
-			<div class="collapse navbar-collapse"
-				id="bs-example-navbar-collapse-1">
-				<ul class="nav navbar-nav">
-					<li><a i18n ng-click="newLicense()"><span
-							class="glyphicon glyphicon-plus"></span> New</a></li>
-					<li><a i18n ng-click="cancel()"> <span
-							class="glyphicon glyphicon-ban-circle"></span> Cancel
-					</a></li>
-				</ul>
-				<div class="navbar-form navbar-right form-group">
-					<span class="input-group input-group-sm">
-							<div class="input-group-addon" style="width: 28px;" >
+				<!-- Collect the nav links, forms, and other content for toggling -->
+				<div class="collapse navbar-collapse"
+					id="bs-example-navbar-collapse-1">
+					<ul class="nav navbar-nav">
+						<li><a i18n ng-click="newLicense()"><span
+								class="glyphicon glyphicon-plus"></span> New</a></li>
+						<li><a i18n ng-click="cancel()"> <span
+								class="glyphicon glyphicon-ban-circle"></span> Cancel
+						</a></li>
+					</ul>
+					<div class="navbar-form navbar-right form-group">
+						<span class="input-group input-group-sm">
+							<div class="input-group-addon" style="width: 28px;">
 								<span class=" glyphicon glyphicon-search"></span>
+							</div> <input type="text" class="form-control" placeholder="Search"
+							ng-model="$searchLicensesText">
+							<div class="input-group-addon" style="width: 20px;">
+								<span class=" glyphicon glyphicon-remove"
+									ng-click="$searchLicensesText = '';"></span>
 							</div>
-							<input type="text" class="form-control" placeholder="Search" ng-model="$searchLicensesText">
-							<div class="input-group-addon" style="width: 20px;" >
-								<span class=" glyphicon glyphicon-remove" ng-click="$searchLicensesText = '';"></span>
-							</div>
-					</span>
+						</span>
 					</div>
-			</div>
+				</div>
 			</div>
 		</nav>
 

--
Gitblit v1.3.2