Implement firmware upload function
Change-Id: Ie89793ec9add1fc9e5241b422cfff64784f7b078
Signed-off-by: Iftekharul Islam <iislam@us.ibm.com>
diff --git a/app/common/directives/file.js b/app/common/directives/file.js
new file mode 100644
index 0000000..11adf8a
--- /dev/null
+++ b/app/common/directives/file.js
@@ -0,0 +1,21 @@
+window.angular && (function (angular) {
+ 'use strict';
+
+ angular
+ .module('app.common.directives')
+ .directive('file', function () {
+ return {
+ scope: {
+ file: '='
+ },
+ link: function (scope, el, attrs) {
+ el.bind('change', function (event) {
+ var file = event.target.files[0];
+ scope.file = file ? file : undefined;
+ scope.$apply();
+ });
+ }
+ };
+ });
+
+})(window.angular);
\ No newline at end of file
diff --git a/app/common/directives/firmware-list.html b/app/common/directives/firmware-list.html
new file mode 100644
index 0000000..91f08a6
--- /dev/null
+++ b/app/common/directives/firmware-list.html
@@ -0,0 +1,67 @@
+<div class="row column firmware__table">
+ <div class="table-header column small-12">
+ <p class="inline">{{title}}</p>
+ <p class="inline firmware__active-version">In-memory firmware version: {{version}}</p>
+ </div>
+ <div class="table row column">
+ <div class="table__head">
+ <div class="table__row">
+ <div class="table__cell">
+ Boot Priority
+ </div>
+ <div class="table__cell">
+ Image state
+ </div>
+ <div class="table__cell">
+ Image ID
+ </div>
+ <div class="table__cell">
+ Version
+ </div>
+ <div class="table__cell">
+ Action
+ </div>
+ </div>
+ </div>
+ <div class="table__body">
+ <div class="table__row" ng-repeat="firmware in firmwares|filter:filterBy">
+ <div class="table__cell firmware__primary">
+ <span class="table__cell-label">Boot Priority:</span>
+ <div class="icon icon__up-arrow icon-as-spacer" aria-hidden="true">
+ <span class="accessible-text">firmware down in priority</span></div>
+ <div class="icon icon__down-arrow" aria-hidden="true">
+ <span class="accessible-text">firmware down in priority</span></div>
+ </div>
+ <div class="table__cell firmware__active">
+ <span class="table__cell-label">Image state:</span><span ng-if="firmware.active">Active</span>
+ </div>
+ <div class="table__cell">
+ <span class="table__cell-label">Image ID:</span>{{firmware.imageId}}
+ </div>
+ <div class="table__cell firmware__version" ng-class="{'active':firmware.isExtended}">
+ <span class="table__cell-label">Version:</span>{{firmware.Version}}
+ <div class="icon icon__more" ng-click="firmware.extended.show = ! firmware.extended.show"
+ ng-class="{'active':firmware.isExtended}" ng-show="firmware.isExtended">
+ <svg version="1.1" x="0px" y="0px" viewBox="0 0 24.3 24.6">
+ <path d="M12.1,23C6.1,23,1.3,18.2,1.3,12.3S6.1,1.6,12.1,1.6s10.7,4.8,10.7,10.7S18,23,12.1,23z M12.1,2.6c-5.4,0-9.7,4.4-9.7,9.7 S6.7,22,12.1,22s9.7-4.4,9.7-9.7S17.4,2.6,12.1,2.6z"/>
+ <g>
+ <circle cx="6.7" cy="12.5" r="1.5"/>
+ <circle cx="12.1" cy="12.5" r="1.5"/>
+ <circle cx="17.4" cy="12.5" r="1.5"/>
+ </g>
+ </svg>
+ </div>
+ <div class="icon__more-dropdown" ng-show="firmware.extended.show">
+ <h5 class="bold">Extended version information</h5>
+ <p class="no-margin" ng-repeat="version in firmware.extended.versions">{{version.title}}: {{version.version}}</p>
+ </div>
+ </div>
+ <div class="table__cell">
+ <span class="table__cell-label">Action:</span>
+ <button class="firmware__action-link" ng-show="!firmware.active" ng-click="activate(firmware.imageId)">Activate</button>
+ <button class="firmware__action-link" ng-show="!firmware.active" ng-click="delete(firmware.imageId)">Delete</button>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
\ No newline at end of file
diff --git a/app/common/directives/firmware-list.js b/app/common/directives/firmware-list.js
new file mode 100644
index 0000000..f4cc94f
--- /dev/null
+++ b/app/common/directives/firmware-list.js
@@ -0,0 +1,28 @@
+window.angular && (function (angular) {
+ 'use strict';
+
+ angular
+ .module('app.common.directives')
+ .directive('firmwareList', ['APIUtils', function (APIUtils) {
+ return {
+ 'restrict': 'E',
+ 'templateUrl': 'common/directives/firmware-list.html',
+ 'scope': {
+ 'title': '@',
+ 'firmwares': '=',
+ 'filterBy': '=',
+ 'version': '='
+ },
+ 'controller': ['$rootScope', '$scope','dataService', '$location', '$timeout', function($rootScope, $scope, dataService, $location, $timeout){
+ $scope.dataService = dataService;
+ $scope.activate = function(imageId){
+ $scope.$parent.activateImage(imageId);
+ }
+
+ $scope.delete = function(imageId){
+ $scope.$parent.deleteImage(imageId);
+ }
+ }]
+ };
+ }]);
+})(window.angular);
\ No newline at end of file
diff --git a/app/common/directives/log-event.html b/app/common/directives/log-event.html
index 2f02315..70d7dee 100644
--- a/app/common/directives/log-event.html
+++ b/app/common/directives/log-event.html
@@ -11,23 +11,22 @@
<button class="btn-primary" ng-click="event.confirm=false;">No</button>
</div>
</div>
- <div class="column small-1 large-1 event-log__col-check">
+ <div class="column small-1 large-2 event-log__col-check">
<label class="control-check">
<input type="checkbox" name="events__check" ng-click="event.selected= ! event.selected"
ng-checked="event.selected"/>
<div class="control__indicator"></div>
</label>
</div>
- <div class="column small-9 large-10 event-log__event-info"
+ <div class="column small-9 large-9 event-log__event-info"
ng-click="event.meta = ! event.meta">
- <p class="inline event__id">#{{event.Id}}</p>
<p class="inline event__priority event-resolved" ng-hide="event.Resolved == 0">Resolved</p>
<p class="inline event__priority med-priority" ng-class="{'low-priority': event.priority == 'Low', 'medium-priority': event.priority == 'Medium', 'high-priority': event.priority == 'High'}" ng-hide="event.Resolved == 1">{{event.priority}}</p>
<p class="inline event__severity">{{event.severity_code}}</p>
- <p class="inline event__timestamp">{{event.Timestamp| date:'MM/dd/yyyy HH:mm:ss '+tmz: tmz}}</p>
+ <p class="inline event__description">{{event.Severity}}</p>
<div>
- <p class="inline event__description">{{event.Severity}}</p>
- </div>
+ <p class="inline event__id">#{{event.Id}}</p>
+ <p class="inline event__timestamp">{{event.Timestamp| date:'MM/dd/yyyy HH:mm:ss '+tmz: tmz}}</p></div>
</div>
<div class="column small-1 large-1">
<button class="accord-trigger" ng-class="{'active': event.meta}"
diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js
index 120bcb8..2df7b5f 100644
--- a/app/common/services/api-utils.js
+++ b/app/common/services/api-utils.js
@@ -476,7 +476,115 @@
}).error(function(error){
console.log(error);
});
- }
+ },
+ getFirmwares: function(callback){
+ $http({
+ method: 'GET',
+ //url: SERVICE.API_CREDENTIALS.mock_host + "/software",
+ url: SERVICE.API_CREDENTIALS.host + "/xyz/openbmc_project/software/enumerate",
+ headers: {
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json'
+ },
+ withCredentials: true
+ }).success(function(response){
+ var json = JSON.stringify(response);
+ var content = JSON.parse(json);
+ var data = [];
+ var active = false;
+ var isExtended = false;
+ var bmcActiveVersion = "";
+ var hostActiveVersion = "";
+ var imageType = "";
+ var extendedVersions = [];
+
+ function getFormatedExtendedVersions(extendedVersion){
+ var versions = [];
+ extendedVersion = extendedVersion.split(",");
+
+ extendedVersion.forEach(function(item){
+ var parts = item.split("-");
+ var numberIndex = 0;
+ for(var i = 0; i < parts.length; i++){
+ if(/[0-9]/.test(parts[i])){
+ numberIndex = i;
+ break;
+ }
+ }
+ var titlePart = parts.splice(0, numberIndex);
+ titlePart = titlePart.join("");
+ titlePart = titlePart[0].toUpperCase() + titlePart.substr(1, titlePart.length);
+ var versionPart = parts.join("-");
+ versions.push({
+ title: titlePart,
+ version: versionPart
+ });
+ });
+
+ return versions;
+ }
+
+ for(var key in content.data){
+ if(content.data.hasOwnProperty(key) && content.data[key].hasOwnProperty('Version')){
+ active = (/\.Active$/).test(content.data[key].Activation);
+ imageType = content.data[key].Purpose.split(".").pop();
+ isExtended = content.data[key].hasOwnProperty('ExtendedVersion') && content.data[key].ExtendedVersion != "";
+ if(isExtended){
+ extendedVersions = getFormatedExtendedVersions(content.data[key].ExtendedVersion);
+ }
+ data.push(Object.assign({
+ path: key,
+ active: active,
+ imageId: key.split("/").pop(),
+ imageType: imageType,
+ isExtended: isExtended,
+ extended: {
+ show: false,
+ versions: extendedVersions
+ },
+ data: {key: key, value: content.data[key]}
+ }, content.data[key]));
+
+ if(active && imageType == 'BMC'){
+ bmcActiveVersion = content.data[key].Version;
+ }
+
+ if(active && imageType == 'Host'){
+ hostActiveVersion = content.data[key].Version;
+ }
+ }
+ }
+ callback(data, bmcActiveVersion, hostActiveVersion);
+ }).error(function(error){
+ console.log(error);
+ });
+ },
+ uploadImage: function(file, callback){
+ $http({
+ method: 'PUT',
+ timeout: 5 * 60 * 1000,
+ //url: 'http://localhost:3002/upload',
+ url: SERVICE.API_CREDENTIALS.host + "/upload/image/",
+ headers: {
+ 'Accept': 'application/octet-stream',
+ 'Content-Type': 'application/octet-stream'
+ },
+ withCredentials: true,
+ data: file
+ }).success(function(response){
+ var json = JSON.stringify(response);
+ var content = JSON.parse(json);
+ if(callback){
+ return callback(content);
+ }
+ }).error(function(error){
+ if(callback){
+ callback(error);
+ }else{
+ console.log(error);
+ }
+ });
+ },
};
return SERVICE;
}]);
diff --git a/app/common/services/constants.js b/app/common/services/constants.js
index dba4afa..7616b3e 100644
--- a/app/common/services/constants.js
+++ b/app/common/services/constants.js
@@ -20,7 +20,8 @@
password: "testpass",
},
API_CREDENTIALS: {
- host: 'https://9.41.165.233/'
+ host: 'https://9.3.185.173',
+ mock_host: 'http://localhost:3000'
},
API_RESPONSE: {
ERROR_STATUS: 'error',
diff --git a/app/common/styles/base/colors.scss b/app/common/styles/base/colors.scss
index 46e7b0a..7308cec 100644
--- a/app/common/styles/base/colors.scss
+++ b/app/common/styles/base/colors.scss
@@ -52,7 +52,6 @@
// Severity
$critical-lightbg: #e62325;
-$critical-bg: #fad3d3;
$critical-darkbg: #ff5c49;
$medium-lightbg: #dc267f;
$medium-darkbg: #FF509E;
diff --git a/app/common/styles/base/foundation.scss b/app/common/styles/base/foundation.scss
index d621b13..9c31f8f 100644
--- a/app/common/styles/base/foundation.scss
+++ b/app/common/styles/base/foundation.scss
@@ -814,7 +814,7 @@
display: block !important; } }
.row {
- max-width: 67.500rem; //960px
+ max-width: 60.38rem; //960px
margin-right: auto;
margin-left: auto; }
.row::before, .row::after {
diff --git a/app/common/styles/base/icons.scss b/app/common/styles/base/icons.scss
index 9772ba4..e499095 100644
--- a/app/common/styles/base/icons.scss
+++ b/app/common/styles/base/icons.scss
@@ -44,7 +44,7 @@
}
}
-.icon__warning {
+.icon__warning{
width: 30px;
height: 30px;
background-image: url(/assets/images/icon-warning.svg);
@@ -52,23 +52,7 @@
vertical-align: middle;
}
-.icon__critical {
- width: 20px;
- height: 20px;
- border-radius: 50%;
- position: relative;
- border-width: 2px;
- border-style: solid;
- color: $critical-lightbg;
- background-color: rgba($critical-bg, 1);
- background-image: url(/assets/images/crit-x.svg);
- background-size: 120%;
- background-position: 50% 50%;
- background-repeat: no-repeat;
- border-color: $critical-lightbg;
-}
-
-.icon__info {
+.icon__info{
margin-top: -4px;
margin-right: .5em;
width: 25px;
@@ -91,7 +75,6 @@
text-align: -9999px;
}
}
-
.icon__down-arrow {
margin-right: 1em;
&:before {
diff --git a/app/common/styles/base/utility.scss b/app/common/styles/base/utility.scss
index b82efc4..33cf61a 100644
--- a/app/common/styles/base/utility.scss
+++ b/app/common/styles/base/utility.scss
@@ -3,7 +3,7 @@
}
.disabled {
- color: darken($lightbg__grey, 10%);
+ color: $lightbg__grey;
}
.float-right {
diff --git a/app/common/styles/elements/modals.scss b/app/common/styles/elements/modals.scss
index 70c0af1..299dfb1 100644
--- a/app/common/styles/elements/modals.scss
+++ b/app/common/styles/elements/modals.scss
@@ -12,6 +12,10 @@
padding:0;
}
+.modal-overlay.active{
+ display: block;
+}
+
.modal {
width:50%;
max-width: 850px;
@@ -31,6 +35,10 @@
}
}
+.modal.active{
+ display: block;
+}
+
.modal .page-header {
padding-bottom: .7em;
}
diff --git a/app/common/styles/elements/quicklinks b/app/common/styles/elements/quicklinks.scss
similarity index 100%
rename from app/common/styles/elements/quicklinks
rename to app/common/styles/elements/quicklinks.scss
diff --git a/app/common/styles/elements/tags.scss b/app/common/styles/elements/tags.scss
index 238a772..8a480c9 100644
--- a/app/common/styles/elements/tags.scss
+++ b/app/common/styles/elements/tags.scss
@@ -103,11 +103,8 @@
border-color: $normal;
&.high-priority {
color: $critical-lightbg;
- background-color: rgba( $critical-bg, 1 );
+ background-color: rgba( $critical-lightbg, .4 );
background-image: url(/assets/images/crit-x.svg);
- background-size: 120%;
- background-position: 50% 50%;
- background-repeat: no-repeat;
border-color: $critical-lightbg;
&:before {
content: '';