summaryrefslogtreecommitdiffstats
path: root/ecomp-portal-FE-os/client/src/views/applications
diff options
context:
space:
mode:
authorst782s <statta@research.att.com>2017-05-04 07:48:42 -0400
committerst782s <statta@research.att.com>2017-05-04 12:28:17 -0400
commitb54df0ddd0c6a0372327c5aa3668e5a6458fcd64 (patch)
treee69cfa9b314a801bd187cf0145d1d4306436229c /ecomp-portal-FE-os/client/src/views/applications
parent39d1e62c84041831bfc52cca73b5ed5efaf57d27 (diff)
[PORTAL-7] Rebase
This rebasing includes common libraries and common overlays projects abstraction of components Change-Id: I9a24a338665c7cd058978e8636bc412d9e2fdce8 Signed-off-by: st782s <statta@research.att.com>
Diffstat (limited to 'ecomp-portal-FE-os/client/src/views/applications')
-rw-r--r--ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.controller.js268
-rw-r--r--ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.controller.spec.js19
-rw-r--r--ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.modal.html201
-rw-r--r--ecomp-portal-FE-os/client/src/views/applications/applications.controller.js123
-rw-r--r--ecomp-portal-FE-os/client/src/views/applications/applications.controller.spec.js19
-rw-r--r--ecomp-portal-FE-os/client/src/views/applications/applications.tpl.html81
6 files changed, 711 insertions, 0 deletions
diff --git a/ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.controller.js b/ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.controller.js
new file mode 100644
index 00000000..da7cd4a4
--- /dev/null
+++ b/ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.controller.js
@@ -0,0 +1,268 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed 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.
+ * ================================================================================
+ */
+'use strict';
+(function () {
+ class AppDetailsModalCtrl {
+ constructor($scope, $log, applicationsService, errorMessageByCode,
+ ECOMP_URL_REGEX,userProfileService, $cookies, confirmBoxService) {
+// let emptyImg = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
+ // empty image should really be empty, or it causes problems for the back end
+ let emptyImg = null;
+ this.emptyImgForPreview = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
+
+ let newAppModel = {
+ 'id': null,
+ 'name': null,
+ 'imageUrl': null,
+ 'description': null,
+ 'notes': null,
+ 'url': null,
+ 'alternateUrl': null,
+ 'restUrl': null,
+ 'isOpen': false,
+ 'username': null,
+ 'appPassword': null,
+ 'thumbnail': emptyImg,
+ 'isEnabled': true,
+ 'restrictedApp': false
+ };
+
+ let init = () => {
+ $log.info('AppDetailsModalCtrl::init');
+ this.isSaving = false;
+ if($scope.ngDialogData && $scope.ngDialogData.app){
+ $log.debug('AppDetailsModalCtrl:init:: Edit app mode for', $scope.ngDialogData.app);
+ this.isEditMode = true;
+ this.app = _.clone($scope.ngDialogData.app);
+ }else{
+ $log.debug('AppDetailsModalCtrl:init:: New app mode');
+ this.isEditMode = false;
+ this.app = _.clone(newAppModel);
+ }
+ this.originalImage = null
+ };
+
+ this.ECOMP_URL_REGEX = ECOMP_URL_REGEX;
+
+ this.imageApi = {};
+ this.removeImage = () => {
+ $log.debug('AppDetailsModalCtrl:removeImage:: entering removeImage');
+
+ confirmBoxService.confirm("Are you sure you want to remove the image?").then(isConfirmed => {
+ if(isConfirmed){
+ this.imageApi.clearFile();
+ this.app.thumbnail = emptyImg;
+ this.originalImage = null;
+ this.app.imageUrl = null;
+ }
+ }).catch(err => {
+ $log.error('AppDetailsModalCtrl:removeImage error:: ',err);
+ });
+ };
+
+ //This part handles conflict errors (409)
+ this.conflictMessages = {};
+ this.scrollApi = {};
+ let handleConflictErrors = err => {
+ if(!err.data){
+ return;
+ }
+ if(!err.data.length){ //support objects
+ err.data = [err.data]
+ }
+ _.forEach(err.data, item => {
+ _.forEach(item.fields, field => {
+ //set conflict message
+ this.conflictMessages[field.name] = errorMessageByCode[item.errorCode];
+ //set field as invalid
+ $scope.appForm[field.name].$setValidity('conflict', false);
+ //set watch once to clear error after user correction
+ watchOnce[field.name]();
+ });
+ });
+ this.scrollApi.scrollTop();
+ };
+
+ let resetConflict = fieldName => {
+ delete this.conflictMessages[fieldName];
+ if($scope.appForm[fieldName]){
+ $scope.appForm[fieldName].$setValidity('conflict', true);
+ }
+ };
+
+
+ let emptyCookies = () => {
+ $log.debug('AppDetailsModalCtrl:emptyCookies:: entering emptyCookies');
+ userProfileService.getUserProfile()
+ .then(profile=> {
+ // $log.info(profile);
+ $scope.orgUserId = profile.attuid;
+ $log.debug('AppDetailsModalCtrl:emptyCookies for the following attuid: ' + profile.attuid);
+ if ($cookies.getObject($scope.orgUserId + '_apps') != undefined && $cookies.getObject($scope.orgUserId + '_apps') != null) {
+ $cookies.remove($scope.orgUserId + '_apps');
+ $log.debug('AppDetailsModalCtrl:emptyCookies removed: ' + $scope.orgUserId + '_apps');
+ }
+ if ($cookies.getObject($scope.orgUserId + '_widget') != undefined && $cookies.getObject($scope.orgUserId + '_widget') != null) {
+ $cookies.remove($scope.orgUserId + '_widget');
+ $log.debug('AppDetailsModalCtrl:emptyCookies removed: ' + $scope.orgUserId + '_widget');
+ }
+ }).catch(err => {
+ $log.error('AppDetailsModalCtrl:emptyCookies error:: '+ JSON.stringify(err));
+ });
+ };
+
+
+ let watchOnce = {
+ name: () => {
+ let unregisterName = $scope.$watch('appDetails.app.name', (newVal, oldVal) => {
+ // $log.debug('newVal, oldVal = ' + newVal.toLowerCase() + " | " + oldVal.toLowerCase())
+ if(newVal.toLowerCase() !== oldVal.toLowerCase()){
+ resetConflict('name');
+ unregisterName();
+ }
+ });
+ },
+ url: () => {
+ let unregisterUrl = $scope.$watch('appDetails.app.url', (newVal, oldVal) => {
+ if(newVal.toLowerCase() !== oldVal.toLowerCase()) {
+ resetConflict('url');
+ unregisterUrl();
+ }
+ });
+ }
+ };
+ //***************************
+
+ this.saveChanges = () => {
+ //if valid..
+ if($scope.appForm.$invalid){
+ return;
+ }
+ this.isSaving = true;
+ // For a restricted app, null out all irrelevant fields
+ if (this.app.restrictedApp) {
+ this.app.restUrl = null;
+ this.app.isOpen = true;
+ this.app.username = null;
+ this.app.appPassword = null;
+ this.app.uebTopicName = null;
+ this.app.uebKey = null;
+ this.app.uebSecret = null;
+ }
+ if(this.isEditMode){
+ applicationsService.updateOnboardingApp(this.app)
+ .then(() => {
+ $log.debug('AppDetailsModalCtrl:updateOnboardingApp:: App update succeeded!');
+ $scope.closeThisDialog(true);
+ emptyCookies();
+ }).catch(err => {
+ switch (err.status) {
+ case '409': // Conflict
+ handleConflictErrors(err);
+ break;
+ case '500': // Internal Server Error
+ confirmBoxService.showInformation('There was a problem updating the application changes. ' +
+ 'Please try again later. Error: ' + err.status).then(isConfirmed => {});
+ break;
+ case '403': // Forbidden... possible webjunction error to try again
+ confirmBoxService.showInformation('There was a problem updating the application changes. ' +
+ 'Please try again. If the problem persists, then try again later. Error: ' + err.status).then(isConfirmed => {});
+ break;
+ default:
+ confirmBoxService.showInformation('There was a problem updating the application changes. ' +
+ 'Please try again. If the problem persists, then try again later. Error: ' + err.status).then(isConfirmed => {});
+ }
+ $log.error('applicationsService:updateOnboardingApp error:: '+ JSON.stringify(err));
+ }).finally(()=>{
+ this.isSaving = false;
+ // for bug in IE 11
+ var objOffsetVersion = objAgent.indexOf("MSIE");
+ if (objOffsetVersion != -1) {
+ $log.debug('AppDetailsModalCtrl:updateOnboardingApp:: Browser is IE, forcing Refresh');
+ $window.location.reload(); // for bug in IE 11
+ }
+ // for bug in IE 11
+ });
+ }else{
+ applicationsService.addOnboardingApp(this.app)
+ .then(() => {
+ $log.debug('App creation succeeded!');
+ $scope.closeThisDialog(true);
+ emptyCookies();
+ }).catch(err => {
+ switch (err.status) {
+ case '409': // Conflict
+ handleConflictErrors(err);
+ break;
+ case '500': // Internal Server Error
+ confirmBoxService.showInformation('There was a problem adding the application information. ' +
+ 'Please try again later. Error: ' + err.status).then(isConfirmed => {});
+ break;
+ default:
+ confirmBoxService.showInformation('There was a problem updating the application changes. ' +
+ 'Please try again. If the problem persists, then try again later. Error: ' +
+ err.status).then(isConfirmed => {});
+ }
+ $log.error('applicationsService:addOnboardingApp error:: '+ JSON.stringify(err));
+ }).finally(()=>{
+ this.isSaving = false;
+ // for bug in IE 11
+ var objOffsetVersion = objAgent.indexOf("MSIE");
+ if (objOffsetVersion != -1) {
+ $log.debug('applicationsService:addOnboardingApp:: Browser is IE, forcing Refresh');
+ $window.location.reload(); // for bug in IE 11
+ }
+ // for bug in IE 11
+ });
+ }
+ };
+
+
+ init();
+
+ $scope.$watch('appDetails.originalImage', (newVal, oldVal) => {
+ if((!newVal || !newVal.resized) && !this.app.imageUrl){
+ if (!newVal) {
+ $log.debug('applicationsService:$scope.$watch:: originalImage: newVal is null');
+ } else {
+ $log.debug('applicationsService:$scope.$watch:: originalImage: newVal is not resized and no imageUrl');
+ }
+ this.app.imageUrl = null;
+ this.app.thumbnail = emptyImg;
+ return;
+ }
+
+ if(!(_.isEqual(newVal, oldVal))){
+ $log.debug('applicationsService:$scope.$watch:: thumbnail updated!');
+ this.app.imageUrl = null;
+ this.app.thumbnail = newVal.resized.dataURL;
+ }
+ });
+
+ $scope.$on('$stateChangeStart', e => {
+ //Disable navigation when modal is opened
+ e.preventDefault();
+ });
+ }
+ }
+ AppDetailsModalCtrl.$inject = ['$scope', '$log', 'applicationsService', 'errorMessageByCode',
+ 'ECOMP_URL_REGEX','userProfileService','$cookies', 'confirmBoxService'];
+ angular.module('ecompApp').controller('AppDetailsModalCtrl', AppDetailsModalCtrl);
+})(); \ No newline at end of file
diff --git a/ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.controller.spec.js b/ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.controller.spec.js
new file mode 100644
index 00000000..34042c14
--- /dev/null
+++ b/ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.controller.spec.js
@@ -0,0 +1,19 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed 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.
+ * ================================================================================
+ */
diff --git a/ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.modal.html b/ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.modal.html
new file mode 100644
index 00000000..ad659aa8
--- /dev/null
+++ b/ecomp-portal-FE-os/client/src/views/applications/application-details-dialog/application-details.modal.html
@@ -0,0 +1,201 @@
+<!--
+ ================================================================================
+ eCOMP Portal
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed 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.
+ ================================================================================
+ -->
+<div class="application-details-modal">
+ <div id="title" class="title">Application Details</div>
+
+ <div class="app-properties-main" scroll-top="appDetails.scrollApi">
+ <form name="appForm" novalidate autocomplete="off">
+ <!-- We can remove this script once we get to AT&T Corporate Firefox version 47
+ autocomplete="off" won't work until v47 -->
+ <script type="text/javascript">
+ document.getElementById("appForm").reset();
+ </script>
+ <div id="app-left-container" class="left-container">
+ <div class="property">
+ <input id="checkbox-app-is-restricted" type="checkbox" class="checkbox-field checkbox-field-openSRC" ng-disabled="appDetails.isEditMode" ng-model="appDetails.app.restrictedApp" ng-checked="appDetails.app.restrictedApp"/>
+ <div class="property-label checkbox-label">Hyperlink only application</div>
+ </div>
+ <div class="property required">
+ <div class="property-label">Application Name</div>
+ <input id="input-app-name" type="text"
+ ng-model="appDetails.app.name"
+ maxlength="100"
+ name="name"
+ ng-pattern="/^[a-zA-Z0-9_\-\s\&]*$/"
+ required/>
+
+ <div id="error-container-conflict" class="error-container" ng-show="appDetails.conflictMessages.name" id="conflictMessages-name">
+ <small id="app-name-error-conflict" class="err-message" ng-bind="appDetails.conflictMessages.name"></small>
+ </div>
+ <div id="error-container-edit" class="error-container" ng-show="appForm.name.$dirty || appDetails.isEditMode">
+ <div ng-messages="appForm.name.$error" class="error-container">
+ <small id="app-name-error-required" class="err-message" ng-message="required">Application name is required</small>
+ <small id="app-name-error-alpha-num" class="err-message" ng-message="pattern">Application name must be alphanumeric</small>
+ </div>
+ </div>
+ </div>
+ <!--<div class="property">-->
+ <!--<div class="property-label">Description</div>-->
+ <!--<input class="input-field" type="text" ng-model="appDetails.app.description"/>-->
+ <!--</div>-->
+ <!--<div class="property">-->
+ <!--<div class="property-label">Notes</div>-->
+ <!--<input class="input-field" type="text" ng-model="appDetails.app.notes"/>-->
+ <!--</div>-->
+ <div class="property required">
+ <div id="url-property-label" class="property-label">URL</div>
+ <input id="input-app-url"
+ ng-model="appDetails.app.url"
+ maxlength="256"
+ name="url"
+ type="url" placeholder="https://"
+ ng-pattern="appDetails.ECOMP_URL_REGEX"
+ required />
+ <div id="app-error-url" class="error-container" ng-show="appDetails.conflictMessages.url" id="div-app-name-err-url">
+ <small class="err-message" ng-bind="appDetails.conflictMessages.url"></small>
+ </div>
+ <div id="app-error-url-message" class="error-container" ng-show="appForm.url.$dirty || appDetails.isEditMode">
+ <div ng-messages="appForm.url.$error" class="error-container">
+ <small id="error-app-url-req" class="err-message" ng-message="required">Application URL is required</small>
+ <!--<small id="error-app-url-invalid" class="err-message" ng-message="pattern">Application URL must be a valid URL</small>-->
+ <small id="error-app-url-invalid" class="err-message" ng-show="appForm.url.$error.url">Application URL must be a valid URL</small>
+ </div>
+ </div>
+ <!--<span class="err-message" ng-show="appForm.url.$error.url"> Not valid URL!</span>-->
+ </div>
+
+
+ <div class="property" ng-show="!appDetails.app.restrictedApp">
+ <div class="property-label">Rest API URL</div>
+ <input id="input-app-rest-url"
+ ng-model="appDetails.app.restUrl"
+ name="restUrl"
+ type="url" placeholder="https://"
+ ng-pattern="appDetails.ECOMP_URL_REGEX"
+ maxlength="256"/>
+ <div id="app-error-rest-message" class="error-container" ng-show="appForm.restUrl.$dirty || appDetails.isEditMode">
+ <div ng-messages="appForm.restUrl.$error" class="error-container">
+ <!--<small class="err-message" ng-message="pattern">Application REST URL must be a valid URL</small>-->
+ <small class="err-message" ng-show="appForm.restUrl.$error.url">Application REST URL must be a valid URL</small>
+ </div>
+ </div>
+ </div>
+
+ <div class="property required" ng-show="!appDetails.app.restrictedApp">
+ <div id="username-property-label" class="property-label">Username</div>
+ <input type="text"
+ ng-model="appDetails.app.username"
+ name="username"
+ maxlength="256"
+ ng-required="!appDetails.app.restrictedApp"/>
+ <div id="app-error-username-container" class="error-container" ng-show="appForm.username.$dirty || appDetails.isEditMode">
+ <div ng-messages="appForm.username.$error" class="error-container">
+ <small id="error-appusername-reqd" class="err-message" ng-message="required">My Logins App Username is required</small>
+ </div>
+ </div>
+ </div>
+ <div class="property required" ng-show="!appDetails.app.restrictedApp">
+ <div id="pwd-property-label" class="property-label">Password</div>
+ <input type="password" id="input-mylogins-password"
+ ng-model="appDetails.app.appPassword" autocomplete="new-password"
+ name="appPassword"
+ maxlength="256"
+ ng-required="!appDetails.app.restrictedApp"/>
+ <div id="app-error-password-container" class="error-container" ng-show="appForm.appPassword.$dirty || appDetails.isEditMode">
+ <div ng-messages="appForm.appPassword.$error" class="error-container">
+ <small id="error-mylogins-password-reqd" class="err-message" ng-message="required">My Logins App Password is required</small>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="right-container">
+ <div class="property">
+ <div class="property-label">Upload Image</div>
+ <input type="file" id="input-app-image-upload"
+ class="input-file-field"
+ accept="image/*"
+ ng-model="appDetails.originalImage"
+ name="appImage"
+ image-upload="appDetails.originalImage"
+ image-upload-resize-max-height="300"
+ image-upload-resize-max-width="360"
+ image-upload-resize-quality="0.7"
+ image-upload-api="appDetails.imageApi" style="height: 24px;"/>
+
+ <div id="app-error-image-upload" class="error-container" ng-show="appForm.appImage.$dirty">
+ <div ng-messages="appForm.appImage.$error" class="error-container">
+ <small id="error-app-invalid-image" class="err-message" ng-message="mimeType">Uploaded file must be an image</small>
+ <small id="error-app-invalid-image-size" class="err-message" ng-message="imageSize">Image file must be smaller than 1MB</small>
+ </div>
+ </div>
+
+ <div class="property-label preview">
+ <span class="left-label">Preview</span>
+ <span class="remove" ng-click="appDetails.removeImage()">Remove</span>
+ </div>
+ <img id="image-app-preview" class="image-preview" ng-src="{{appDetails.app.imageLink || appDetails.app.thumbnail || appDetails.emptyImgForPreview}}"/>
+ <div id="property-communication-inbox" class="property" ng-show="!appDetails.app.restrictedApp">
+ <div id="property-communication-inbox-label" class="property-label">Communication Inbox</div>
+ <input type="text" id="input-UEB-topicname"
+ ng-model="appDetails.app.uebTopicName"
+ name="uebTopicName" readonly="readonly"/>
+ </div>
+
+ <div id="property-communication-key" class="property" ng-show="!appDetails.app.restrictedApp">
+ <div id="property-communication-key-label" class="property-label">Communication Key</div>
+ <input type="text" id="input-UEB-communication-key"
+ ng-model="appDetails.app.uebKey"
+ name="uebKey" readonly="readonly" />
+ </div>
+
+ <div id="property-communication-secret" class="property" ng-show="!appDetails.app.restrictedApp">
+ <div id="property-communication-secret-label" class="property-label">Communication Secret</div>
+ <input type="text" id="input-UEB-communication-secret"
+ ng-model="appDetails.app.uebSecret"
+ name="uebSecret" readonly="readonly" />
+ </div>
+
+ <div id="property-guest-access" class="property">
+ <input id="checkbox-app-is-open" type="checkbox" class="checkbox-field checkbox-field-openSRC" ng-model="appDetails.app.isOpen" ng-checked="appDetails.app.isOpen || appDetails.app.restrictedApp" ng-disabled="appDetails.app.restrictedApp"/>
+ <div id="property-guest-checkbox-label" class="property-label checkbox-label">Allow guest access</div>
+ </div>
+ <div id="property-active" class="property">
+ <input id="checkbox-app-is-enabled" type="checkbox" class=" checkbox-field checkbox-field-openSRC " ng-model="appDetails.app.isEnabled"/>
+ <div id="property-active-checkbox-label" class="property-label checkbox-label">Active</div>
+ </div>
+
+ </div>
+
+ </div>
+ </form>
+ </div>
+
+ <div class="dialog-control">
+ <span class="ecomp-save-spinner" ng-show="appDetails.isSaving"></span>
+ <button id="button-save-app" class="btn btn-alt btn-small" ng-class="{disabled: appForm.$invalid}" ng-click="appDetails.saveChanges()">Save</button>
+ <button id="button-app-cancel" class="btn btn-alt btn-small" ng-click="closeThisDialog()">Cancel</button>
+ </div>
+</div>
+
+<script type="application/javascript">
+ $(document).ready(function(){
+ $(".ngdialog-content").css("top","-150px")
+ });
+</script> \ No newline at end of file
diff --git a/ecomp-portal-FE-os/client/src/views/applications/applications.controller.js b/ecomp-portal-FE-os/client/src/views/applications/applications.controller.js
new file mode 100644
index 00000000..08f00669
--- /dev/null
+++ b/ecomp-portal-FE-os/client/src/views/applications/applications.controller.js
@@ -0,0 +1,123 @@
+/*-
+ * ================================================================================
+ * eCOMP Portal
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed 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.
+ * ================================================================================
+ */
+'use strict';
+(function () {
+ class ApplicationsCtrl {
+
+ constructor($log, $cookies, conf, ngDialog,
+ applicationsService, confirmBoxService, userProfileService, utilsService) {
+ this.emptyImgForPreview = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
+ let getOnboardingApps = () => {
+ this.isLoadingTable = true;
+ applicationsService.getOnboardingApps()
+ .then(appsList => {
+ // Use proper back-end URL to load image
+ for (var i = 0; i < appsList.length; i++) {
+ appsList[i].imageLink = '';
+ if (appsList[i].imageUrl)
+ appsList[i].imageLink = conf.api.appThumbnail.replace(':appId', appsList[i].id);
+ }
+ this.appsList = appsList;
+ }).catch(err => {
+ confirmBoxService.showInformation('There was a problem retrieving the Applications. ' +
+ 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {});
+ $log.error('ApplicationsCtrl:openAddNewAppModal: Error: ', err);
+ }).finally(()=> {
+ this.isLoadingTable = false;
+ });
+ };
+
+ let init = () => {
+ this.isLoadingTable = false;
+ getOnboardingApps();
+ this.searchString = '';
+ this.appsTableHeaders = [
+ {name: 'Application Name', value: 'name', isSortable: true},
+ {name: 'Active', value: 'isEnabled', isSortable: true},
+ {name: 'Integration Type', value: 'restrictedApp', isSortable: true},
+ {name: 'Guest Access', value: 'isOpen', isSortable: true},
+ {name: 'URL', value: 'url', isSortable: true},
+ {name: 'REST URL', value: 'restUrl', isSortable: true},
+ {name: 'Communication Topic', value: 'uebTopicName', isSortable: true},
+ {name: 'Communication Key', value: 'uebKey', isSortable: true},
+ {name: 'Communication Secret', value: 'uebSecret', isSortable: true},
+ ];
+ this.appsList = [];
+ };
+
+ init();
+
+ this.openAddNewAppModal = (selectedApp) => {
+ let data = null;
+ if (selectedApp) {
+ if (!selectedApp.id) {
+ $log.error('App id not found');
+ return;
+ }
+ data = {
+ app: selectedApp
+ }
+ }
+ ngDialog.open({
+ templateUrl: 'app/views/applications/application-details-dialog/application-details.modal.html',
+ controller: 'AppDetailsModalCtrl',
+ controllerAs: 'appDetails',
+ data: data
+ }).closePromise.then(needUpdate => {
+ if (needUpdate.value === true) {
+ $log.debug('ApplicationsCtrl:openAddNewAppModal: updating table data...');
+ getOnboardingApps();
+ }
+ });
+
+
+ };
+
+ this.deleteApp = application => {
+ $log.debug('ApplicationsCtrl:deleteApp:: ', application.name);
+
+ confirmBoxService.deleteItem(application.name).then(isConfirmed => {
+ if(isConfirmed){
+ if(!application || !application.id){
+ $log.error('ApplicationsCtrl:deleteApp:: No application or ID... cannot delete');
+ return;
+ }
+ applicationsService.deleteOnboardingApp(application.id).then(() => {
+ this.appsList.splice(this.appsList.indexOf(application), 1);
+ }).catch(err => {
+ confirmBoxService.showInformation('There was a problem deleting the Application. ' +
+ 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {});
+ $log.error('ApplicationsCtrl:deleteApp: Error: ', err);
+ });
+ }
+ }).catch(err => {
+ confirmBoxService.showInformation('There was a problem deleting the Application. ' +
+ 'Please try again later. Error Status: '+ err.status).then(isConfirmed => {});
+ $log.error('ApplicationsCtrl:deleteApp error:: ', err);
+ });
+
+ };
+
+ }
+ }
+ ApplicationsCtrl.$inject = ['$log', '$cookies', 'conf', 'ngDialog',
+ 'applicationsService', 'confirmBoxService', 'userProfileService', 'utilsService'];
+ angular.module('ecompApp').controller('ApplicationsCtrl', ApplicationsCtrl);
+})();
diff --git a/ecomp-portal-FE-os/client/src/views/applications/applications.controller.spec.js b/ecomp-portal-FE-os/client/src/views/applications/applications.controller.spec.js
new file mode 100644
index 00000000..3841a2b3
--- /dev/null
+++ b/ecomp-portal-FE-os/client/src/views/applications/applications.controller.spec.js
@@ -0,0 +1,19 @@
+/*-
+ * ================================================================================
+ * ECOMP Portal
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property
+ * ================================================================================
+ * Licensed 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.
+ * ================================================================================
+ */
diff --git a/ecomp-portal-FE-os/client/src/views/applications/applications.tpl.html b/ecomp-portal-FE-os/client/src/views/applications/applications.tpl.html
new file mode 100644
index 00000000..edded4bb
--- /dev/null
+++ b/ecomp-portal-FE-os/client/src/views/applications/applications.tpl.html
@@ -0,0 +1,81 @@
+<!--
+ ================================================================================
+ eCOMP Portal
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property
+ ================================================================================
+ Licensed 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.
+ ================================================================================
+ -->
+<div class="w-ecomp-main">
+ <div class="w-ecomp-main-container">
+
+ <div class="applications-page-main" id="page-content">
+ <div id='app-title' class="w-ecomp-main-view-title">
+ <h1 class="heading-page" >Application Onboarding</h1>
+ </div>
+ <div class="apps-table">
+ <div class="table-control">
+ <div class="table-control-fields">
+ <div >
+ <input id="input-table-search" placeholder="Search in entire table" class="table-search-field" type="text" data-ng-model="searchAppName">
+ </div>
+ </div>
+ <div class="table-control-buttons">
+ <button class="btn btn-alt btn-small" ng-click="apps.openAddNewAppModal()"><i class="icon-people-userbookmark" aria-hidden="true"></i>&nbsp;Add App</button>
+ </div>
+ </div>
+ <span class="ecomp-spinner" ng-show="apps.isLoadingTable"></span>
+
+
+ <div b2b-table table-data="apps.appsList" ng-hide="apps.isLoadingTable" search-string="searchAppName" class="b2b-table-div">
+ <table>
+ <thead b2b-table-row type="header">
+ <th b2b-table-header id="col1" sortable="false" >Thumbnail</th>
+ <th b2b-table-header id="col2" key="name" sortable="true" >Application Name</th>
+ <th b2b-table-header id="col3" sortable="false" >Active?</th>
+ <th b2b-table-header id="col4" sortable="false" >Integration Type</th>
+ <th b2b-table-header id="col5" sortable="false" >Guest Access</th>
+ <th b2b-table-header id="app-header-URL" sortable="false">URL</th>
+ <th b2b-table-header id="app-header-RESTURL" sortable="false">REST URL</th>
+ <th b2b-table-header id="app-header-Topic" sortable="false">Communication Topic</th>
+ <th b2b-table-header id="app-header-CommKey" sortable="false">Communication Key</th>
+ <th b2b-table-header id="app-header-Secret" sortable="false">Communication Secret</th>
+ <th b2b-table-header id="app-header-delete" sortable="false">Delete</th>
+ </tr>
+ </thead>
+ <tbody b2b-table-row type="body" row-repeat="rowData in apps.appsList">
+ <tr>
+ <td b2b-table-body id="rowheader_t1_{{$index}}" headers="col1" ng-click="apps.openAddNewAppModal(rowData)">
+ <img id="{{$index}}-app-imageUrl" class="small-thumbnail" ng-src="{{rowData.imageLink || apps.emptyImgForPreview}}">
+ </td>
+ <td b2b-table-body headers="rowheader_t1_{{$index}} col2" ng-bind="rowData.name" ng-click="apps.openAddNewAppModal(rowData)"></td>
+ <td b2b-table-body headers="rowheader_t1_{{$index}} col3" ng-click="apps.openAddNewAppModal(rowData)">{{(rowData.isEnabled) ? 'yes' : 'no'}}</td>
+ <td b2b-table-body headers="rowheader_t1_{{$index}} col4" ng-click="apps.openAddNewAppModal(rowData)">{{(rowData.restrictedApp) ? 'link' : 'standard'}}</td>
+ <td b2b-table-body headers="rowheader_t1_{{$index}} col5" ng-click="apps.openAddNewAppModal(rowData)">{{(rowData.isOpen) ? 'yes' : 'no'}}</td>
+ <td b2b-table-body headers="rowheader_t1_{{$index}} col7" ng-click="apps.openAddNewAppModal(rowData)">{{rowData.url | elipsis: 27}}</td>
+ <td b2b-table-body headers="rowheader_t1_{{$index}} col8" ng-click="apps.openAddNewAppModal(rowData)">{{rowData.restUrl | elipsis: 27}}</td>
+ <td b2b-table-body headers="rowheader_t1_{{$index}} col11" ng-click="apps.openAddNewAppModal(rowData)"ng-bind="rowData.uebTopicName"></td>
+ <td b2b-table-body headers="rowheader_t1_{{$index}} col12" ng-click="apps.openAddNewAppModal(rowData)"ng-bind="rowData.uebKey"></td>
+ <td b2b-table-body headers="rowheader_t1_{{$index}} col13" ng-click="apps.openAddNewAppModal(rowData)"ng-bind="rowData.uebSecret"></td>
+ <td b2b-table-body headers="rowheader_t1_{{$index}} col14" >
+ <span class="icon-misc-trash" ng-click="apps.deleteApp(rowData)"></span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file